Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
Tags
- 스파르타코딩클럽 #부트캠프 #IT #백엔드 #OSI #ISO #AI #서버 #자동화 #SQL #기본문법 #데이터베이스 #DBMS #Oracle #MongoDB #아키텍쳐 #DB
- 스파르타코딩클럽 #부트캠프 #IT #백엔드 #머신러닝 #AI #서버 #자동화 #SQL #KDT #기본문법 #데이터베이스 #Computer #Science #CPU #메모리
- aws #클라우드 #퍼블릭 클라우드 #아키텍트 #과정
- aws #아키텍트 #과정 #vpc #인프라 구축
- aws #아키텍트 #과정 #vpc #인프라 구축 #public subnet #igw #curl #명령어 #http
- aws #아키텍트 #과정 #vpc #인프라 구축 #public subnet #private subnet
- 스파르타코딩클럽 #부트캠프 #IT #백엔드 #머신러닝 #AI #서버 #자동화 #SQL #기본문법 #데이터베이스
- 스파르타코딩클럽 #부트캠프 #IT #백엔드 #머신러닝 #딥러닝 #AI #서버 #자동화 #SQL #기본문법 #데이터베이스
- 공간복잡도 #공간자원 #캐시메모리 #SRAM #DRAM #시간복잡도
- aws #아키텍트 #과정 #vpc #인프라 구축 #public subnet #route53 #igw #연결
- mysql #linux #설정 #wordpress #웹사이트 #db 연결 #
- ubuntu #설정변경 #vmware #vmbox #linux #명령어
- aws #아키텍트 #과정 #vpc #인프라 구축 #퍼블릭 서브넷 #안에 #ec2 인스턴스 #ami #생성 #firewall
- 프로세스 #CPU #시공유 #커널
- 스파르타코딩클럽 #부트캠프 #IT #백엔드 #머신러닝 #딥러닝 #AI #서버 #자동화 #SQL #기본문법 #데이터베이스 #DBMS #Oracle #MongoDB #아키텍쳐 #DB
- 스파르타코딩클럽 #부트캠프 #IT #백엔드 #머신러닝 #AI #서버 #자동화 #SQL #기본문법 #데이터베이스 #웹개발
- 비트 #바이트 #이진수
- samba #가상머신 #daemon
- oracle vmbox #rocky #linux9 #명령어 #암호화인증 #해시알고리즘
- aws #아키텍트 #과정 #vpc #인프라 구축 #public subnet #internet gateway #연결
- 쓰레드 #쓰레드풀 #프로세스
- aws #아키텍트 #과정 #s3 #bucket #생성 #이미지업로드
- aws #아키텍트 #과정 #vpc #인프라 구축 #퍼블릭 #보안그룹 #생성 #http #ipv4
- virtualbox #vmware #router #nat #pat #네트워크 구성도 #aws #ubuntu #
- sasac #aws 클라우드 #아키텍트 과정 #가상화 #vmbox #vmware #esxi #tar #selinux
- storage #로컬스토리지 #세션스토리지 #백그라운드 서비스
- aws #아키텍트 #과정 #vpc #인프라 구축 #php #웹페이지 #http #public #instance
- 인바운드 #아웃바운드 #방화벽설정
- tar #build #배포 #통신포트 #설정방법 #linux #apache
- haproxy #wordpree #php #linux #가상화 #가상머신 #내용정리
Archives
- Today
- Total
요리사에서 IT개발자로
스파르타 코딩클럽(부트캠프) 4장 프로세스 쓰레드와 쓰레드 본문
쓰레드 : 프로세스 내 에서 실행되는 실행단위
쓰레드 풀 : 쓰레드를 미리 생성해 두어 작업 처리에 사용되는 쓰레드를 제한된 갯수 만큼 정해놓고 작업 큐에 등어오는 작업들을 하나씩 쓰레드가 맡아 처리하는 기법
쓰레드 풀 장/단점
1.쓰레드를 생성/수거 하는데 비용이 들지않는다
2.쓰레드 풀을 미리 만들어 두기에 시스템 자원을 줄일 수 있다.
3.쓰레드 풀에 쓰레드를 너무 많이 생성해두었다가 사용하지 않으면 메모리 낭비가 발생
프로세스와 쓰레드
프로그램을 실행해주는 주체 = 프로세스
작업을 처리해주는 주체 = 쓰레드
프로세스 안에 업무를 분담하는 역할 = 쓰레드
- ex)메시지 발송을 처리하는 쓰레드, 메시지 수신을 확인하는 쓰레드 등
- 쓰레드는 필요할 때마다 생성되며, 프로세스 상세의 스레드 수는 최근 평균 스레드 갯수 통계
프로세스 : 자신만의 고유 공간과 자원을 할당받아 사용
쓰레드 : 공간과 자원을 다른 쓰레드와 공유하며 사용
쓰레드
프로세스와 쓰레드의 차이점
프로세스 : 자신만의 고유공간과 자원을 할당받아 사용한다.
- 프로세스는 메모리 상에서 실행중인 프로그램, 쓰레드는 이 프로세스 안에서 실행되는 흐름 단위
- 프로세스는 최소 하나의 쓰레드를 보유, 각각 별도의 주소공간을 독립적으로 할당(Code, Heap, Stack)
프로세스 만으로 처리할 때 문제점
1.프로세스 생성에 큰 오버헤드가 있어서 많은 시간이 소요된다.
2.프로세스 컨텍스트 스위칭의 비효율성, 오버헤드가 크다.
3.프로세스 사이에 비용이 비싼 IPC를 사용해서 통신이 어렵다.
IPC란 Inter-Process Communication 프로세스간 통신을 위한 매커니즘
프로세스간 데이터를 주고받기위한 방법
Message Queue, Shared Memory, Semaphore, Socket 등
쓰레드 : 공간과 자원을 다른 쓰레드와 공유하며 사용
- 쓰레드는 프로세스안에서 작업을 처리하는 주체
- 쓰레드는 자원 중 Stack만 따로 할당, 나머지 영역은 쓰레드끼리 공유
쓰레드가 해결한 문제들
1. 프로세스보다 크기가 작은 실행 단위 구현
2. 프로세스의 생성 및 소멸에 따른 오버헤드 감소
3. 쓰레드간 자원을 공유함으로써 빠른 컨텍스트 스위칭
4. 프로세스 들의 통신 시간, 방법 어려움 해소
프로세스와 쓰레드 비교
프로세스 : 운영체제로부터 별도의 메모리 영역을 할당
쓰레드 : Stack을 제외한 Code/Data/Heap 부분은 공유하여 서로 읽고 쓸 수 있다.(공유 자원)
- 운영체제는 프로세스마다 독립된 영역을 Code/Data/Stack/Heap의 형식으로 할당
- 각각 독립된 메모리 영역을 할당해주기에 프로세스는 다른 프로세스의 변수나 자료에 접근불가
- 쓰레드는 메모리를 서로 공유할 수 있다.
- 프로세스가 할당받은 메모리 영역 내에서 Stack 형식으로 할당된 메모리 영역은 따로 할당, 나머지 Code/Data/Heap 형식으로 할당된 메모리 영역을 공유
- 각각의 쓰레드는 별도의 스택을 갖고 있으나 힙메모리는 서로 읽고 쓸 수 있다.
- 각자 업무하는 공간에 같이보는 Code, Data, Heap을 같이 쓴다
프로세스와 쓰레드의 주소공간
프로세스의 주소공간
프로세스를 알기전 프로그램을 알아야 한다.
프로그램(Program)은 어떤 작업을 위해 실행할 수 있는 파일
프로세스의 사전적 정의
1. 컴퓨터에서 연속적 실행하고 있는 컴퓨터 프로그램
2. 메모리에 올라와 실행되고 있는 프로그램의 인스턴스(독립적인 개채)
3. 운영체제로부터 시스템 자원을 할당받는 자원의 단위
4. 프로그램의 실행된 부분을 의미
프로세스특징
그림에서 여러 프로세스가 동시에 실행되고 관리되는 것처럼 보이나, CPU는 한 번에 한 가지 명령밖에 처리할 수 없다.동시가 아니라 빠르게 프로세스들을 번갈아가며 실행하고 관리하는 것.
- 각각 독립된 메모리 영역(Code, Data, Stack Heap)을 할당
- 최소 1개 이상의 스레드 (메인 스레드)를 갖고 있다
- 각 프로세스는 별도의 주소 공간에서 실행되며 기본적으로 다른 프로세스의 자원에 접근불가
- 한 프로세스가 다른 프로세스의 자원에 접근하려면 프로세스 간 통신(IPC)을 사용해야 한다.
- Ex) 파이프, 파일, 소켓 등을 이용한 통신 방법
코드 영역 (Code Area) : 프로그래머가 작성한 프로그램이 저장되는 영역
데이터 영역(Data Area) : 코드가 실행되면서 사용한 환경이나 파일들의 각종 데이터들이 모여있다.
스택 영역(Stack Area) : 호출한 함수가 종료되면 되돌아올 메모리의 주소나 지역 변수 등이 저장된다.
힙 영역(Heap Area) : 동적으로 할당되는 데이터를 위해 존재한다
쓰레드의 주소공간
쓰레드의 사전적 정의
1. 프로세스 내에서 실행되는 여러 흐름의 단위
2. 프로세스의 특정한 수행 경로
3. 프로세스가 할당받은 자원을 이용하는 최소 실행 단위
쓰레드의 특징
1. 프로세스 내에서 각 필요한 Stack만 할당받고 Code, Data, Heap 영역은 각 스레드가 공유한다
2. 같은 프로세스 내 스레드끼리 자원(Heap 등)을 공유하며 실행된다
3. 쓰레드는 공유하는 자원(Heap 영역)의 변수를 수정 할 수 있다.
4. 프로세스 하나만을 사용해서 프로그램을 실행하기에 메모리의 낭비가 발생한다.
5. 쓰레드는 프로세스와 다르게 스레드 간에 메모리를 공유하며 작동된다.
6. 프로세스가 할당받은 자원을 이용하는 처리 작업(실행의 흐름)의 단위이다
공간(Slack) 에서 Code, Data, Heap을 같이 쓴다
스레드가 독립적으로 갖고 있는 부분 = 작업 흐름과 관련
- Program Counter
- Register Set
- Stack Space
스레드가 동료 스레드와 공유하는 부분 = 작업 데이터와 관련
- Code Section
- Data Section
- OS resources
전통적인 개념의 Heavy Weight Process 는 "하나의 Thread를 가지고 있다"라는 작업으로 볼 수 있다.
멀티 프로세스와 멀티 쓰레드
멀티 프로세스 : 하나의 운영체제 안에서 여러프로세스가 실행되는 것
멀티 쓰레드 : 하나의 프로세스가 여러 작업을 여러 쓰레드를 사용하여 동시에 처리하는것
종류 | 멀티 프로세스 | 멀티 쓰레드 |
장점 | 1. 하나의 프로세스가 죽어도 다른 프로세스에 영향을 끼치지 않는다. | 1. 프로세스를 생성하여 자원을 할당하는 시스템 콜이 줄어들어 자원을 효율적으로 관리가 가능하다. 2. Code, Data,Heap 영역을 공유하기에 데이터를 주고 받는 것이 간단 해지고 자원 소모가 적다. 3. 쓰레드 간의 작업량이 적어 문맥교환이 빠르고 시스템 처리량이 증가한다. |
단점 | 1.각각 독립된 메모리 영역을 가지고 있어 작업량이 많을수록 오버헤드가 발생하고 문맥 교환(Context Switching)으로 인한 성능 저하를 유발한다. 2.프로세스 간 통신이 복잡하다.(IPC 등) |
1. 프로그램 디버깅이 까다롭다(에러 추적) 2. 하나의 쓰레드에 문제가 생길시 전체적인 프로세스에 영향을 끼친다. 3. 동기화 문제가 발생한다.(전역 변수를 사용하기에) 4. 단일 프로세스 시스템에서 효과를 기대하기 어렵다. 5. 다른 프로세스에서 쓰레드 제어가 불가능하다 |
멀티 프로세싱
하나의 프로그램을 여러개의 프로세스가 구성하여 각 프로세스가 작업(Task)를 처리하도록 하는 기법
(멀티 태스킹과 비슷한 의미)
멀티 프로세스 특징
1. 여러개의 자식 프로세스 중 하나에 문제가 발생해도 다른 자식 프로세스는 영향을 받지 않는다
2. Context Switching 과정에서 캐쉬 메모리 초기화 등 무거운 작업이 진행되며 오버헤드가 발생한다.
3. 프로세스 간에 통신을 하기위해서는 IPC를 통해야한다.
4. 프로세스 간에 공유하는 메모리가 없어 Context Switching이 발생하면 데이터를 처음부터 불러와야 한다.
문맥 교환 (Context Switching)
CPU 코어를 여러 프로세스가 돌아가면서 사용하는 작업을 처리하는 방식
해당 프로세스의 상태(Context)를 자신의 PCB에 저장하고 대기하고 있던 다음 순서의 프로세스가 이전의 프로세스 상태를 복구하는 작업
멀티쓰레딩
하나의 응용프로그램을 여러 개의 쓰레드로 구성하고 각 쓰레드가 하나의 작업을 처리하도록 하는 것.
윈도우나 리눅스 등 많은 OS에서 멀티 프로세싱도 지원하나 멀티 쓰레딩을 기본으로 한다.
멀티스레드 특징
1. 시스템 자원 소모가 감소한다.(자원의 효율성)
- 프로세스를 생성하여 자원을 할당하는 시스템 콩이 줄어 자원을 효율적으로 관리 할 수 있다.
2. 시스템 처리량이 감소한다(처리 비용)
-쓰레드 간 데이터를 주고 받는 것이 간단해지며 시스템 자원 소모가 줄어든다.
-쓰레드 사이 작업량이 적어 쓰레드 간에 Context Switching이 활발하게 일어난다.
멀티쓰레드 단점
1. Thread-Safety 에 문제가 없는 지 확실한 설계가 필요하다.
2. 디버깅이 까다롭다.
3. 동기화나 교착상태가 발생할 수 있다
4. 프로세스 밖에서는 해당 쓰레드를 제어 할 수 없다.
5. 하나의 쓰레드가 문제가 발생할 시 프로세스 전체가 영향을 받는다.
교착상태란
둘 이상의 쓰레드가 서로의 작업이 끝나기만을 기다리며 작업을 더 이상 진행하지 못하는 상태를 의미
멀티프로세스 대신 멀티 쓰레드를 사용하는 이유
- 자원 효율성 증대
- 처리 비용 감소
- 응답 시간 단축
- 프로세스 생성 시 자원을 할당하는 시스템 콜이 줄어 자원소모가 적으며, 자원을 효율적으로 관리 할 수 있다.
- 또한 프로세스의 경우 Context Switching 시 CPU 레지스터, RAM과 CPU 사이의 캐시메모리가 초기화 대기에 오버헤드가 큰 반면, 쓰레드는 Context Switching 시 Stack 영역만 처리하면 됨으로 쓰레드 간 문맥 교환 속도가 빠르다.
- 그리고 프로세스의 경우 프로세스 간 통신을 위해서 IPC를 통해 통신을 해야하나, 쓰레드는 쓰레드 간 자원 공유가 간단하기에 시스템 자원소모가 작다
- 그러나 전역 변수를 통해 쓰레드 간 자원을 공유 하기에 동기화 문제는 잘 해결 해야한다.
멀티 쓰레드의 장점
- Context- Switching 할 때 공유하고 있는 메모리만큼 메모리 자원을 아낄 수 있다.
- 쓰레드는 프로세스 내의 Stack 영역을 제외한 모든 메모리를 공유하기에 통신부담이 적어 응답시간이 빠르다.
멀티 쓰레드의 단점
- 쓰레드 하나가 프로세스 내 자원을 망칠 시 모든 프로세스가 종료될 수 있다.
- 자원을 공유하기에 필연적으로 동기화 문제가 발생할 수 밖에 없다. (교착상태가 발생하지않도록 주의)
멀티 쓰레드의 동기화 문제
멀티 쓰레드를 사용하면 각각의 쓰레드 중 어떤 것이 어떤 순서로 실행될지 순서를 파악할 수 없다.
1. A 쓰레드가 어떤 자원을 사용하다가 B쓰레드로 제어권이 넘어간다.
2. B쓰레드가 자원을 수정한다.
3. A쓰레드가 제어권을 받고 해당자원에 접근하지 못한다.
4. 결론 = 바뀐 자원에 접근하지 못하게 되는 오류가 발생할 수 있다
동기화문제
여러 쓰레드가 함께 전역 변수를 사용할 경우 발생할 수 있는 충돌을 동기화문제
스케쥴링은 운영체제가 자동으로 해주지 않기에 프로그래머가 적절한 기법을 구현해야 함으로 프로그래밍 할 때 멀티쓰레드를 사용하려면 신중해야한다.
쓰레드는 운영체제의 스케쥴러에 의해 독립적으로 관리될 수 있는 프로그래밍된 언어의 가장 작은 흐름.
하나의 프로세스는 하나 이상의 쓰레드를 가지고 있다.
멀티프로세스 : 하나의 운영체제 안에 여러 프로세스가 실행되는 것
멀티 쓰레드 : 하나의 프로세스가 여러작업을 여러 쓰레드를 사용하여 동시에 처리하는 것
쓰레드 풀
쓰레드 풀이란
작업 처리에 사용되는 쓰레드를 제한된 갯수만큼 정해 놓고 작업 큐(Queue)에 들어오는 작업들을 하나씩 쓰레드가 맡아 처리하는 것을 말한다.
- 컴퓨터 프로그래밍에서 쓰레드 풀은 컴퓨터 프로그램에서 실행의 동시성을 달성하기 위한 소프트 웨어 디자인 패턴
- 프로그램이 작업을 동시에 실행할 수 있도록 여러 쓰레드를 미리 생성해두고 유지 관리한다.
- 여러 Thread를 동시에 만들어 실행(병렬처리) 할 수 있다.
Thread를 계속 늘려가면 좋지 않다.
하드웨어의 제한적인 사항(CPU, Memory 등) 이 있기에 관리할 필요가 있어 쓰레드 풀이라는 개념을 이용한다.
쓰레드 풀의 동작
- 초기화 : 쓰레드 풀을 사용하기 전 초기화를 해야한다. 이 단계에서 쓰레드 풀의 크기, 최대 쓰레드 수, 작업 큐 등의 매개변수를 성정해야한다.
- 작업 수신 : 쓰레드 풀은 작업을 수신하고 처리할 준비를 한다. 작업은 일반적으로 작업 큐에 추가된다.
- 작업 수행 : 쓰레드 풀에서는 미리 생성된 쓰레드들이 작업 큐를 모니터링 하고 대기중인 작업을 가져와 처리한다. 이 때 쓰레드 풀 내 쓰레드들은 일반적으로 무한루프를 돌며 작업을 가져오기 위해 대기한다.
- 작업 처리 : 쓰레드 풀의 쓰레드가 작업을 가져와 처리한다. 작업은 일반적으로 작업 큐에 FIFO(선입선출) 방식으로 가져온다.
- 작업 완료 및 반환 : 작업이 완료되면 해당 결과를 반환, 쓰레드는 다시 작업 큐에서 새로운 작업을 가져오기 위해 대기 상태로 돌아간다.
- 작업대기 : 작업 큐에 새로운 작업이 추가되면 쓰레드 풀의 쓰레드들은 대기 상태를 벗어나 작업을 가져와 처리한다. 이를 반복하여 계속적으로 작업을 수행함.
- 종료 : 쓰레드 풀을 더이상 사용하지 않을 경우 종료된다. 종료할 때 모든 작업이 완료되었는지 확인하고 필요에 따라 남은 작업들을 처리하거나 버릴 수 있다.
쓰레드 풀을 사용하는 이유
1. 프로그램 성능 저하를 방지하기 위해
- 매번 발생하는 작업을 병렬처리하기 위해 쓰레드를 생성/수거 하는 데 따른 부담은 프로그램 전체적인 퍼포먼스를 저하시킨다. 따라서 쓰레드 풀을 만들어 놓고 사용한다.
- 쓰레드 또한 프로세스가 할당한 메모리를 사용한다.
- Java의 경우 쓰레드를 생성하면 JVM 메모리를 소비하게 되는것이다. 쓰레드 자체도 레지스터와 스택을 가지고 있지만 쓰레드도 컨텍스트 스위칭이 일어나기에 쓰레드 생성에 따른 메모리 할당을 무시할 수 없다.
2. 다수의 사용자 요청을 처리하기 위해
- 대규모 프로젝트에서 특히 중요하다.
- 다수 사용자의 요청을 수용, 빠르게 처리, 대응 을 위해 쓰레드 풀을 사용
- 특히 Bottle Neck 현상이 발생하는 I/O 작업과 데이터베이스 작업에서 주로 사용
- 쓰레드가 아무리 빠르게 생성되더라도 시스템 스케쥴러에서 쓰레드의 우선순위를 매번 할당해야 하는데 쓰레드 풀을 이용하게되면 일정 쓰레드가 이미 생성되어 쓰레드 풀에 의해 라이프 사이클이 관리, 쓰레드 풀에 의하여 작업이 큐를 이용, 우선순위가 배분되고 처리된다.
쓰레드 풀의 장/단점
장점
- 쓰레드를 생성/수거 에 비용이 들지 않는다.
- 쓰레드가 생성될 경우 OS가 메모리 공간을 확보, 메모리를 쓰레드에게 할당한다.
- 쓰레드 풀을 미리 만들어 두기에 처음 생성하는 비용은 들지만 이전의 쓰레드를 재사용 함으로 시스템 자원 절감, 작업 요청시 이미 쓰레드가 대기중인 상태이므로 작업을 실행할 경우 딜레이가 발생되지 않는다.
단점
- 쓰레드 풀에 쓰레드를 너무 많이 생성해 두었다가 사용하지 않으면 메모리 낭비가 발생한다.
- 쓰레드 풀의 단점 개선 : Fork, Join Thread Pool
기존 쓰레드 풀을 개선하기 위한 방법, Java 7 이상의 쓰레드 풀에서 사용되고 있다.
기본적으로 큰 업무를 작은 업무로 나누어 배분, 일을 한 후에 일을 취한 한 형태
동시성 (Concurrency)과 병렬성(Parallelism)
동시성
- 싱글 코어에서 멀티 쓰레드를 동작시키기 위한 방식
- 멀티 태스킹을 위해 여러개의 쓰레드가 번갈아가며 실행되는 성질
- 동시성을 이용한 싱글코어의 멀티태스킹은 쓰레드들이 병렬적으로 실행되는 것 처럼 보이나 사실은 번갈아가며 조금씩 실행되는 것이다.
병렬성
- 멀티코어에서 멀티 쓰레드를 동작 시키는 방식.
- 한 개 이상의 쓰레드를 포함시키는 각 코어들이 동시에 실행되는 성질.
- 병렬성은 데이터 병렬성(Data Parallelism)과 작업 병렬성(Task Parallelism) 으로 구분된다.
데이터 병렬성
- 전체 데이터를 나누어 서브 데이터들로 만든 뒤 ,서브 데이터들을 병렬 처리하여 작업을 빠르게 수행하는것.
- 자바 8에서 지원하는 병렬 스트림이 데이터 병렬성을 구현한 것.
- 서브 데이터는 "멀티 코어의 수" 만큼 쪼개어 각각의 데이터들을 분리된 쓰레드에서 병렬처리 한다.
작업 병렬성
- 서로 다른 작업을 병렬 처리하는 것
- 대표적인 예 : 웹서버가 각각의 브라우저에서 요청한 내용을 개별 쓰레드에서 병렬로 처리한다.
쓰레드 풀 한줄요약
작업 처리에 사용되는 쓰레드를 갯수를 제한하여 작업큐에 들어오는 작업들을 하나씩 쓰레드가 처리하는 기법
반응형
'Computer Science' 카테고리의 다른 글
스파르타 코딩클럽(부트캠프) 6장 DBMS(데이터베이스 관리 시스템)의 기능과 종류 (1) | 2024.03.22 |
---|---|
스파르타 코딩클럽(부트캠프) 5장 DB(데이터베이스) 구조와 유형 (0) | 2024.03.21 |
스파르타 코딩클럽(부트캠프) 3장 프로세스 생명주기와 프로세스메모리 (2) | 2024.03.19 |
스파르타 코딩클럽(부트캠프) 2장CPU 와 메모리 심화 (0) | 2024.03.18 |
스파르타 코딩클럽(부트캠프) 1장 CPU 와 메모리 (2) | 2024.03.15 |