- Published on
멀티스레드와비동기란?
- Authors
- Name
- zkrp
안녕하세요 이번에 도서관 프로젝트를 하던 도중에 멀티스레딩과 비동기의 개념이 필요할거 같아서 공부하는겸 글을 남길려 합니다!
일단 이해하기 쉽게 멀티 스레드/단일 스레드 와 동기/비동기 개념에 대해 작성 하겠습니다.
1. 개념
1-1) 단일 스레드 vs 멀티 스레드
1. 단일 스레드
단일 스레드는 비유를 통해 설명하자면 '하나의 일꾼(스레드)'가 모든 작업을 순차적으로 처리하는 것을 의미합니다.
2. 멀티 스레드
멀티스레드는 비유를 통해 설명하자면 '여러 명의 일꾼(스레드)'가 동시에 일을 나눠서 처리하는것을 의미합니다.
- 여러 작업을 동시에 물리적으로 처리가 가능합니다.
- 각 스레드가 하나의 코어를 점유하여 독립적으로 작업을 수행합니다.
- 각 스레드가 동시에 여러 작업을 병렬로 처리할 수 있어서 ,CPU 연산 위주 작업등에서 성능을 향상시킬수 있습니다.
1-2) 동기(Synchronous) vs 비동기(Asynchronous)
1. 동기
동기 프로그래밍을 비유를 통해 설명하자면 한 명의 일꾼(단일 스레드가) 한 작업이 끝날 때 까지 기다리고, 일이 다 끝난 다음에 다음 작업을 시작하는것을 의미합니다.
- 각 연산이 순서대로 실행되므로 코드의 흐름을 이해하기 쉽고 예측 가능합니다.
2. 비동기
비동기 프로그래밍을 비유를 통해 설명하자면 한 명의 일꾼(단일 스레드)이 있어도, 한 작업이 끝날 때까지 기다리는 것이 아니라, 기다리는 시간 동안 다른 작업을 처리하는 효율적인 작업 흐름을 의미합니다.
- I/O대기 동안 기다리지 않고 다른 작업을 처리할 수 있어 효율적입니다.
- 전체 작업의 처리 시간을 단축할 수 있으며 사용자 경험을 향상시킬 수 있습니다.
이해하기 쉽게 카페를 비유로 설명하겠습니다.
1-3) 비유
1. 동기 방식
한 명의 바리스타가 주문받고, 커피 내리고, 전달까지 완전히 끝내야만 다음 손님 주문을 받습니다.
- 줄이 길어지면 뒤 손님들은 하염없이 기다려야합니다.
2. 멀티 스레딩 방식
- 바리스타를 여러 명(스레드) 고용. 각 바리스타가 한 손님씩 전담 마크합니다.
- 카페 전체 처리량은 늘어나지만, 바리스타(스레드)를 많이 고용하면 인건비(메모리, 컨텍스트 스위칭 비용)가 많이 듭니다.
3. 비동기 방식
유능한 바리스타 한 명(단일 스레드)이 일을 하는방식입니다.
- A 손님 주문을 받고 커피 머신(I/O 작업) 작동 버튼을 누릅니다.
- 커피가 추출되는 동안 기다리지 않고, 바로 B 손님 주문을 받습니다.
- B 손님의 스무디 믹서 버튼을 누르고, C 손님 주문을 받습니다.
- 중간에 커피 머신이 완료 알림(Callback, Event)을 주면, A 손님에게 커피를 전달합니다.
이것만 보면 멀티스레드, 비동기를 사용하면 무조건 성능이 향상이 되겠다! 라고 생각할 수 있지만 전혀 아닙니다.
그 이유를 설명하겠습니다.
2. 멀티 스레드와 비동기의 단점
첫 번째로 멀티스레드의 단점에 대해 설명하겠습니다.
1. 멀티 스레드 단점
1. 메모리 할당
- 각 스레드는 자신만의 호출 스택을 가지고 있어야합니다.
- 스레드 생성할 때는 호출 스택을 위한 메모리 할당해야합니다.
- 자바에서 스레드 하나 생성 시 기본 스택 크기가 약 1MB (JVM 옵션 -Xss로 조절 가능)
- 스레드 1만 개 띄우려면 최소 10GB 필요합니다. (스택만 해도)
- 그래서 무한정 스레드를 만들 수 없습니다.
- 스레드 생성할 때는 호출 스택을 위한 메모리 할당해야합니다.
2. 운영체재 자원 사용
- 자바 스레드는 JVM 레벨 추상화이지만, 실제로는 OS 커널 스레드 위에서 동작합니다
- 자바 코드 → JVM → 시스템 콜(clone) → OS 커널이 PCB/TCB 만들고 스택 할당 → 스케줄러 등록
- 스레드를 생성하는 작업은 운영체제 커널 수준에 이루어져서 CPU와 메모리 리소스를 소모합니다.
- 자바 코드 → JVM → 시스템 콜(clone) → OS 커널이 PCB/TCB 만들고 스택 할당 → 스케줄러 등록
3. 컨텍스트 스위칭
CPU가 한 스레드 실행 중에 다른 스레드로 넘어갈 때, 레지스터/프로그램 카운터/캐시 상태를 저장하고 불러오는 과정입니다.
- 비용 요소
- 캐시 미스(Cache Miss): CPU 캐시에 있던 데이터가 날아가고, 다시 메모리에서 읽어야 합니다.
- 레지스터/스택 포인터 저장·복원을 해야합니다.
- 시스템 콜 트랩 발생 시 커널 모드 ↔ 사용자 모드 전환
- 비용 크기
- 스케줄링 대상 스레드가 늘어나면 CPU가 작업보다 스레드 전환에 더 많은 시간을 씁니다.
- 나노초 단위지만, 초당 수백만 번 발생할수도 있어서 누적되면 성능이 저하 됩니다.
- 특히 I/O 대기 많은 서버에서 스레드 과잉 생성을 하게되면 컨텍스트 스위칭 폭발뿐만 아니라 CPU가 일 처리보다 스레드 전환만 하게 됩니다.
이제 비동기 방식의 단점에 대해 설명하겠습니다.
2. 비동기 단점
1. 코드 복잡성 증가
- 동기 코드보다 흐름을 추적하기 어렵습니다.
2. CPU 바운드 작업에 효과 없음
- 비동기는 I/O 대기 최적화에 초점을 둬서 반대로 연산이 많은 작업은 멀티스레드/멀티코어 병렬처리가 필요합니다.
3. 예상치 못한 동작
- 비동기 작업은 실행 순서를 정확히 예측하기 어렵습니다.
- 여러 비동기 요청이 동시에 보내질 때, 어느 요청이 먼저 완료될지 보장할 수 없습니다.
멀티스레드나 비동기 모두 장점만 있는 건 아닙니다.
멀티스레드는 스레드 생성 비용, 메모리 소비, 컨텍스트 스위칭 때문에 무작정 늘릴 수 없습니다.
비동기 프로그래밍은 스레드 자원을 절약하면서 많은 I/O 요청을 효율적으로 처리할 수 있지만, 코드 복잡성 증가와 디버깅 어려움이라는 단점이 있습니다.
따라서 CPU 바운드 작업은 멀티스레드, I/O 바운드 작업은 비동기 모델을 적용하는 식으로 문제에 맞는 전략을 선택하는 것이 중요합니다.
다음 글에는 이 개념을 가지고 실전에서 어떻게 사용할수 있는지 작성하려합니다!