"모든 동시성 모델은 결국 같은 두 질문 — '블로킹을 어떻게 피하는가'와 '공유 상태를 어떻게 보호하는가' — 에 다르게 답한 것이다"
"한 언어의 동시성을 잘 쓰는 것과, 모든 모델이 같은 트레이드오프 공간의 다른 점이라는 걸 아는 것은 다르다"
JVM Virtual Thread · Kotlin Coroutine · Go 고루틴 · Rust async · Swift async/Actor · JS Event Loop — 6개 동시성 모델을 한자리에 놓고 같은 과제를 6번 풀어 효율·안전성·표현력의 축에서 비교합니다. 왜 모두 협력적 스케줄링으로 수렴했는가, 그리고 안전성에선 왜 갈라졌는가.
동시성 자료는 언어별로는 넘쳐납니다. 하지만 대부분은 "한 언어 안에서 어떻게 쓰나" 에서 멈춥니다. 이 레포는 언어가 아니라 질문으로 챕터를 나누고, 각 질문에 대해 6모델의 답을 나란히 놓습니다.
| 일반 자료 | 이 레포 |
|---|---|
| "고루틴 = 코루틴" | 고루틴은 스택풀 + 런타임 스케줄러, 코루틴은 스택리스 + 컴파일러 상태머신 — 같은 결과를 완전히 다른 방법으로 |
| "async/await는 JS 문법" | Kotlin·Rust·Swift·JS의 async가 모두 같은 상태머신 변환이라는 점, 그리고 색깔 함수 문제가 만드는 분기 |
| "Rust는 안전하다" | 안전성을 어디서 보장하는가 — Rust(컴파일 타임 타입), Swift(컴파일 타임 격리), JVM(런타임 락), Go(관례 + race detector) |
| "Virtual Thread = 코루틴 대체" | VT는 JVM 변경으로 얻은 런타임 다중화, 코루틴은 컴파일러 변환 — 색깔 함수의 유무가 만드는 본질적 차이 |
| "구조적 동시성은 Kotlin 거" | Kotlin·Swift·Java가 독립적으로 같은 결론에 도달한 수렴점, 그러나 Go의 누수 위험이 끝까지 남는 이유 |
| 단일 모델 설명 | 동일 과제 6언어 구현 — 1만 동시 작업 + 집계 + 타임아웃 + 취소를 같은 부하로 측정 |
| 추상적 비교 | 트레이드오프 공간을 2축 좌표(컴파일/런타임 안전 × 색깔 유무)에 6모델을 플롯 |
선행 학습 권장: 이 레포는 6개 단일 언어 deep-dive 레포의 종합입니다. 한 언어라도 먼저 보고 오면 비교의 깊이가 다릅니다 — 🔗 레포 연결 참고.
질문별로 챕터가 구성되어 있습니다. 각 챕터의 첫 문서부터 바로 시작하세요.
모든 동시성 모델 = 두 질문에 대한 답의 조합
① 효율: 스레드를 어떻게 싸게 쓰나?
OS 스레드(비쌈) → 경량 단위로 다중화
→ 6모델 모두 "양보 지점에서 멈추고 스레드 재사용"으로 수렴
→ 갈라지는 지점: 스택풀(Go·VT) vs 스택리스(Kotlin·Rust·Swift·JS)
② 안전: 공유 상태를 어떻게 지키나?
락(JVM) — 런타임 보장, 실수 가능
Actor(Swift) — 컴파일 타임 격리
소유권(Rust) — 컴파일 타임 타입, 런타임 비용 0
채널(Go) — 공유 대신 통신(CSP)
트레이드오프 공간:
컴파일 타임 안전 ◄─────────────────► 런타임/관례
Rust ● ● JVM
Swift ● ● Go
색깔 있음 ◄─────────────────► 색깔 없음
Rust/JS ● ● Go/JVM VT
💡 각 섹션을 클릭하면 상세 문서 목록이 펼쳐집니다. 모든 문서에서 최소 2~3개 모델을 나란히 비교합니다.
핵심 질문: 모든 동시성 모델이 답하는 두 질문은 무엇이며, 이 레포는 어떤 축으로 그것들을 비교하는가?
두 질문, 블로킹의 비용, 동시성 vs 병렬성, 레이스의 본질까지 (5개 문서)
| 문서 | 다루는 내용 |
|---|---|
| 01. 두 가지 근본 질문 | 모든 모델이 답해야 하는 ① 스레드 효율 ② 상태 안전, 그리고 둘이 독립적인 트레이드오프 축임을 보이는 6모델 매핑 |
| 02. 블로킹의 비용 | OS 스레드 블로킹이 비싼 이유 — 1MB 스택·커널 TCB·컨텍스트 스위치, C10K 문제, linux-for-backend 레포로 깊이 위임 |
| 03. 동시성 vs 병렬성 | "Concurrency is not parallelism" (Rob Pike) — 단일 코어에서도 동시성이 의미 있는 이유, 6모델이 각각 어디에 무게를 두는가 |
| 04. 공유 상태와 레이스 | 데이터 레이스의 본질(메모리 모델·재정렬·가시성), computer-architecture-deep-dive로 깊이 위임, 6모델이 어디에서 막는가 |
| 05. 비교 프레임 설정 | 이 레포가 사용할 4개 평가 축 — 효율(처리량·메모리) / 안전성(보장 위치) / 표현력(색깔·구조) / 복잡도(러닝커브·디버깅) |
핵심 질문: OS 스레드가 비싼 이유와, 6모델이 그 비용을 피한 서로 다른 방법은 무엇인가?
OS 스레드, 협력적 스케줄링, VT, 고루틴, 상태머신, 나란히 측정까지 (6개 문서)
| 문서 | 다루는 내용 |
|---|---|
| 01. OS 스레드는 왜 비싼가 | 1MB 스택·TCB·clone 시스템 콜·커널 스케줄러 — 수만 개가 원리적으로 불가능한 이유, 6모델이 공유하는 출발점 |
| 02. 협력적 스케줄링 — 공통 답 | 6모델 모두가 도달한 결론: 양보 지점에서 멈추고 재개 — preemptive와의 차이, 각 모델이 양보를 어디에 두는가 |
| 03. Virtual Thread (JVM) | 캐리어 스레드 위 다중화, 블로킹 코드를 그대로 쓸 수 있는 특이점, pinning 함정, java-concurrency-deep-dive로 위임 |
| 04. 고루틴 (Go) | M:N GMP 스케줄러, 2KB 시작 가변 스택, 워크 스틸링 — 런타임이 자체 스케줄러를 갖는 모델, go-deep-dive로 위임 |
| 05. 상태머신 코루틴 (Kotlin·Rust·Swift·JS) | 4개 언어가 독립적으로 도달한 같은 변환 — suspend/async → 상태머신 객체, 동형성 강조 |
| 06. 측정 비교 — 1만 동시 작업 | 같은 부하(1만×100ms 대기)를 6모델로, 메모리·생성 시간·처리량을 같은 그래프에, OS 스레드 1만(불가)을 대조군으로 |
핵심 질문: "양보"를 구현하는 두 가지 방식 — 스택풀과 스택리스 — 은 무엇이 다르며, 색깔 함수는 어디서 생기는가?
두 방식, 상태머신 변환, 스택풀, 색깔 함수, Continuation까지 (6개 문서)
| 문서 | 다루는 내용 |
|---|---|
| 01. 스택풀 vs 스택리스 | 두 가지 갈래 — Go·VT(스택 보유) vs Kotlin·Rust·Swift·JS(상태머신) — 이 분기가 만드는 결과들의 전체 지도 |
| 02. 상태머신 변환의 동형성 | Kotlin suspend, Rust async fn, Swift async가 바이트코드/IR 레벨에서 같은 상태머신이 됨을 디컴파일로 확인 |
| 03. 스택풀 코루틴 — Go·VT 내부 | 고루틴의 stack growth check·세그먼티드 스택, VT의 캐리어 위 컨텍스트 스위치 — 실제 스택을 양보하는 메커니즘 |
| 04. 색깔 함수 문제 | "What Color is Your Function?" (Bob Nystrom) — async 전염(JS/Rust/Kotlin/Swift) vs 무색(Go/VT), 타입 시스템 격리의 가치와 비용 |
| 05. Continuation — 공통 추상 | 일시정지/재개의 저수준 — Kotlin Continuation, Rust Future::poll+Waker, Swift task UnsafeContinuation — 같은 개념의 다른 이름 |
| 06. 같은 비동기 로직 6모델 | 동일한 "fetch → transform → fetch → aggregate" 로직을 6언어로 — 색깔 유무가 코드 모양을 어떻게 바꾸나 |
핵심 질문: 같은 데이터 레이스가 Rust에선 컴파일 에러, JVM에선 런타임 버그가 되는 이유는?
네 가지 전략, 락, Actor, 소유권, 채널, 보장 위치 비교까지 (7개 문서)
| 문서 | 다루는 내용 |
|---|---|
| 01. 네 가지 전략 | ① 공유+락 ② 격리(Actor) ③ 소유권+타입 ④ 통신(채널) — 6모델이 어떤 전략을 주력으로 채택했는가의 매핑 |
| 02. 공유 + 락 (JVM) | synchronized·ReentrantLock·volatile·CAS, 런타임 보장의 한계 — 잊으면 끝, java-concurrency-deep-dive로 위임 |
| 03. 격리 — Actor (Swift) | actor가 가변 상태를 직렬화하는 메커니즘, Swift 6의 컴파일 타임 Sendable 검사, swift-concurrency-deep-dive로 위임 |
| 04. 소유권 + 타입 (Rust) | Send/Sync 자동 트레이트가 컴파일 타임에 레이스를 막는 원리, 런타임 비용 0의 안전성, rust-deep-dive로 위임 |
| 05. 통신 — 채널 (Go) | "Don't communicate by sharing memory; share memory by communicating" — CSP, select, go-deep-dive로 위임 |
| 06. 안전성 위치 비교 | 어디서 막는가의 4단 분기 — 컴파일 타임 타입(Rust) / 컴파일 타임 격리(Swift) / 런타임 검사(JVM) / 관례+도구(Go) |
| 07. 같은 레이스 6모델 | 동일한 공유 카운터 증가 코드를 6언어로 — Rust는 컴파일 거부, Swift는 경고, Go는 -race로 검출, JVM은 실리콘 운에 맡김 |
핵심 질문: 비동기 작업이 떠도는 것을 막는 메커니즘은 무엇이며, 왜 여러 언어가 같은 결론에 도달했는가?
구조적 동시성, 취소 전파, 누수 위험, 에러 전파까지 (5개 문서)
| 문서 | 다루는 내용 |
|---|---|
| 01. 구조적 동시성 | Nathaniel Smith의 원안 — 작업 트리·생명주기를 부모 함수 스코프에 묶기, Kotlin·Swift·Java가 독립적으로 수렴한 결론 |
| 02. 취소 전파 | 부모 취소 → 자식 취소가 자동인 모델(Kotlin·Swift) vs 수동인 모델(Go context, JS AbortController) — 안전성 차이 |
| 03. 비구조적 위험 | 떠도는 태스크 — Go의 고루틴 누수, Kotlin의 GlobalScope 안티패턴, JS의 unhandled Promise — 같은 함정의 다른 이름 |
| 04. 에러 전파 | 동시 작업 중 하나가 실패할 때의 전파 정책 — Kotlin SupervisorJob, Swift withThrowingTaskGroup, Go errgroup, JS Promise.all vs allSettled |
| 05. 같은 시나리오 6모델 | "여러 작업 동시 실행 + 하나 실패 시 전체 취소 + 타임아웃" — 6언어 구현을 같은 코드 모양으로 정렬해 비교 |
핵심 질문: 동일한 동시성 과제를 6개 언어로 짜면 코드 모양과 측정값이 어떻게 다르게 나오는가?
과제 정의, 6언어 구현, 코드 비교, 측정 비교까지 (6개 문서) — comparisons/ 에 실행 가능 코드
| 문서 | 다루는 내용 |
|---|---|
| 01. 과제 정의 | 통일된 과제 — 동시 API 호출 N개 + 집계 + 5초 타임아웃 + 하나 실패 시 전체 취소, 입출력 명세, 측정 지표 |
| 02. 구현 ① JVM Virtual Thread / ② Kotlin Coroutine | 두 JVM 솔루션 — VT는 블로킹 그대로, Kotlin은 coroutineScope+async — 같은 런타임, 다른 코드 |
| 03. 구현 ③ Go 고루틴+채널 / ④ Rust async (Tokio) | Go: errgroup+context, Rust: tokio::try_join!+select! — 스택풀 vs 스택리스의 코드 모양 차이 |
| 04. 구현 ⑤ Swift async/Actor / ⑥ JS async/Promise | Swift: withThrowingTaskGroup+actor, JS: Promise.all+AbortController — 구조적 동시성의 언어 차원 통합도 |
| 05. 코드 비교 — 가독성·안전성·표현력 | 6언어 구현을 나란히 한 표에 — 줄 수, 명시적 취소 코드 비율, 에러 처리 명확성, 타입 안전성 점수 |
| 06. 측정 비교 — 처리량·메모리·지연 | 같은 부하(N=10,000)에서 6모델의 p50/p99 지연, RSS, GC pause, CPU 활용도를 같은 그래프에 |
핵심 질문: 6모델이 왜 효율에선 수렴했고 안전성에선 갈라졌는가, 그리고 새 언어를 만나도 빠르게 분석할 수 있는 프레임은?
평가 축, 수렴, 발산, 선택 가이드, 종합 지형도까지 (5개 문서)
| 문서 | 다루는 내용 |
|---|---|
| 01. 평가 축 종합 | 효율·안전성 위치·색깔·런타임 유무·복잡도 — 5축에 6모델을 한 표로 정렬, 각 칸의 점수 근거 |
| 02. 왜 수렴했나 | 협력적 경량 스케줄링으로 모두 간 이유 — OS 추상화의 한계, 하드웨어 코어 정체, I/O 비중 증가 |
| 03. 왜 발산했나 | 안전성 철학의 분기 — 타입 (Rust) vs 격리 (Swift) vs 런타임 (JVM) vs 관례 (Go) — 언어 설계 가치관의 차이 |
| 04. 선택 가이드 | 워크로드 × 팀 × 생태계에 따른 모델 이해 — "어느 게 좋다"가 아니라 "이 상황에선 이 트레이드오프가 맞다" |
| 05. 동시성 모델 지형도 | 종합 — 새 언어의 동시성을 만나도 이 프레임으로 1시간 안에 파악, 향후 등장할 모델의 예측(예: Mojo, Zig async) |
🟢 "고루틴 = 코루틴?"을 명확히 구분하고 싶다 — 면접/개념 정리 (1주)
Day 1 Ch1-01 두 가지 근본 질문 (틀 잡기)
Day 2 Ch2-04 고루틴 (Go) — 스택풀 + 런타임 스케줄러
Day 3 Ch2-05 상태머신 코루틴 — 4언어 동형
Day 4 Ch3-01 스택풀 vs 스택리스 (핵심 분기)
Day 5 Ch3-04 색깔 함수 문제
Day 6 Ch2-06 측정 비교 — 1만 동시 작업
Day 7 Ch7-03 왜 발산했나 — 철학의 차이
🔵 모든 동시성 모델을 원리부터 비교하고 싶은 개발자 (7주)
Week 1 Chapter 1 전체 — 근본 문제와 평가 프레임
Week 2 Chapter 2 전체 — 효율의 6가지 답
Week 3 Chapter 3 전체 — 일시정지 메커니즘
Week 4 Chapter 4 전체 — 안전성의 4가지 전략
Week 5 Chapter 5 전체 — 구조와 취소
Week 6 Chapter 6 전체 — 같은 과제 6언어 구현 + 측정
Week 7 Chapter 7 전체 — 종합과 선택 가이드
🔴 새 언어의 동시성을 빠르게 평가하는 프레임이 필요한 개발자 (집중 코스)
핵심 경로 — "프레임 먼저, 사례는 나중"
Step 1 Ch1-01 두 질문 (효율 + 안전)
Step 2 Ch1-05 4개 평가 축
Step 3 Ch3-01 스택풀 / 스택리스 분기
Step 4 Ch3-04 색깔 함수 (타입 시스템 격리)
Step 5 Ch4-01 안전성 4전략
Step 6 Ch4-06 안전성 보장 위치
Step 7 Ch7-01 평가 축 종합 표
Step 8 Ch7-05 지형도 — 새 모델 평가 템플릿
목표: 처음 보는 언어의 동시성 모델을 1시간 안에
"이 좌표의 이 점이다"라고 말할 수 있을 것
🟡 안전성 모델만 깊게 보고 싶은 개발자
Step 1 Ch1-04 레이스의 본질
Step 2 Ch4-01 네 가지 전략
Step 3 Ch4-02 락 (JVM) — 런타임
Step 4 Ch4-04 소유권 (Rust) — 컴파일 타임 타입
Step 5 Ch4-03 Actor (Swift) — 컴파일 타임 격리
Step 6 Ch4-05 채널 (Go) — CSP
Step 7 Ch4-07 같은 레이스 6모델 비교
Step 8 Ch7-03 왜 발산했나 — 철학의 분기
모든 문서는 동일한 10섹션 구조 + 이 레포의 정체성: 항상 다중 모델 나란히 비교.
| 섹션 | 설명 |
|---|---|
| 🎯 핵심 질문 | 이 문서를 읽고 나면 답할 수 있는 질문 |
| 🔍 왜 이게 존재하는가 | 6모델 공통의 문제 상황과 각 모델이 답해야 했던 압력 |
| 😱 흔한 오해 | "코루틴 = 고루틴", "Rust는 무조건 안전" 같은 교차 모델 오해들 |
| ✨ 올바른 이해 | 각 모델이 왜 그런 답을 골랐는지의 설계 의도 |
| 🔬 내부 동작 원리 | 최소 2~3개 모델을 같은 표·다이어그램에 — 한 모델만 설명하지 않음 |
| 💻 실전 실험 | 동일한 과제를 여러 언어로 구현 (comparisons/ 에 실행 가능) |
| 📊 측정 | 같은 부하·같은 머신·같은 그래프에 6모델 데이터 — 처리량·메모리·지연 |
| 🤔 트레이드오프 | 4개 평가 축(효율·안전·표현력·복잡도)에 각 모델을 플롯 |
| 📌 핵심 정리 | 한 화면 요약 — 6모델의 한 줄 비교 |
| 🤔 생각해볼 문제 | 교차 모델 사고 실험 + 해설 |
다언어 비교라 여러 런타임을 한 번에.
docker-compose로 polyglot 환경,comparisons/에 동일 과제 6구현.
# Dockerfile — 6모델 비교용 polyglot
FROM ubuntu:24.04
RUN apt-get update && apt-get install -y \
openjdk-21-jdk \ # JVM Virtual Thread (Project Loom)
golang-1.22 \ # 고루틴
nodejs npm \ # JS Event Loop
curl build-essential
# Rust async (Tokio)
RUN curl https://sh.rustup.rs -sSf | sh -s -- -y
# Kotlin (SDKMAN)
RUN curl -s "https://get.sdkman.io" | bash && \
bash -c "source ~/.sdkman/bin/sdkman-init.sh && sdk install kotlin"
# Swift 6 (별도 멀티스테이지 또는 swift:6 베이스 이미지 권장)# 핵심 — 같은 과제를 6언어로, 나란히 측정
# [효율 비교] 1만 동시 "100ms 대기" 작업
cd comparisons/10k-tasks
./run-jvm-vt.sh # Virtual Thread
./run-kotlin.sh # Coroutine + Dispatchers.IO
./run-go.sh # goroutine
./run-rust.sh # Tokio task
./run-swift.sh # Task + TaskGroup
./run-node.sh # async/await + Promise.all
# 측정: 메모리(RSS), 생성 시간, 처리량
# 대조: OS 스레드 1만 (불가/거대)
# [안전 비교] 공유 카운터에 1만 동시 증가
cd comparisons/shared-counter
cargo build # → Rust: 컴파일 에러 (Send/Sync 위반)
swift build # → Swift 6: 컴파일 경고 (Sendable)
go build # → 빌드 성공, go run -race 로 런타임 검출
./gradlew run # → JVM: 런타임 레이스 (도구로 검출 필요)
# [색깔 비교] async 전염 관찰
cd comparisons/function-coloring
# Rust/JS: async fn → 호출자도 async (전염)
# Go/JVM VT: 일반 함수처럼 블로킹 코드 그대로 (무색)
# Kotlin/Swift: suspend/async 키워드 + 구조적 동시성검증 결과는 각 문서 📊 측정 섹션에 *같은 그래프*로 통합.
숫자는 머신마다 다르므로 절대값보다 비율/순위에 주목.
⬆️ 선행 학습 (이 비교의 입력 — 한 언어라도 먼저)
java-concurrency-deep-dive → Virtual Thread, 락, 메모리 모델
kotlin-deep-dive → Coroutine, CPS 변환, 상태머신
go-deep-dive → 고루틴, GMP 스케줄러, 채널
rust-deep-dive → async/await, Send/Sync, Tokio
swift-concurrency-deep-dive → async/await, Actor, Sendable
event-loop-async-deep-dive → JS 이벤트 루프, Promise, 마이크로태스크
🤝 시너지
computer-architecture-deep-dive → 메모리 모델, 원자 연산, 캐시 일관성
linux-for-backend-deep-dive → 스레드 스케줄링, epoll/io_uring, C10K
🧬 본질 (이 레포의 위치)
concurrency-models-compared → 6개 단일 레포를 하나의 비교 프레임으로
"한 언어 동시성"과 "트레이드오프 공간 이해"의 다리
- Bob Nystrom — "What Color is Your Function?"
- Nathaniel Smith — "Notes on structured concurrency, or: Go statement considered harmful"
- Rob Pike — "Concurrency is not Parallelism"
- Brian Goetz et al. — Java Concurrency in Practice
- Roman Elizarov — "Deep Dive into Coroutines" 발표들
- Tony Hoare — "Communicating Sequential Processes" (CSP 원안)
- JEP 444 — Virtual Threads
- Swift Evolution — SE-0306 Actors
- Rust async book
- Go memory model
- 각 선행 레포의 참고자료 — 이 레포는 그 종합
⭐️ 도움이 되셨다면 Star를 눌러주세요!
Made with ❤️ by Dev Book Lab
"한 언어의 동시성을 잘 쓰는 것과, 모든 모델이 같은 트레이드오프 공간의 다른 점이라는 걸 아는 것은 다르다"