이벤트 루프
싱글 스레드 환경에서 비동기 작업을 처리하는 메커니즘입니다. 주로 JavaScript(브라우저, Node.js)에서 사용됩니다.
왜 필요한가
JavaScript는 싱글 스레드입니다. 한 번에 하나만 실행할 수 있어요.
// 이러면 3초 동안 화면이 멈춤
sleep(3000);
console.log("완료");
하지만 실제로는 API 호출, 타이머 등을 기다리지 않고 처리합니다. 이게 이벤트 루프 덕분입니다.
구조
┌─────────────────────────────┐
│ Call Stack │ ← 현재 실행 중인 코드
└─────────────────────────────┘
↑
│ 꺼내서 실행
│
┌─────────────────────────────┐
│ Callback Queue │ ← 대기 중인 콜백들
└─────────────────────────────┘
↑
│ 완료되면 콜백 등록
│
┌─────────────────────────────┐
│ Web APIs / libuv │ ← 비동기 작업 처리 (별도 스레드)
│ (setTimeout, fetch 등) │
└─────────────────────────────┘
동작 과정
console.log("1");
setTimeout(() => {
console.log("2");
}, 0);
console.log("3");
출력: 1 → 3 → 2
1. console.log("1") 실행 → 출력: 1
2. setTimeout 만남 → Web API에게 넘김 (타이머 시작)
3. console.log("3") 실행 → 출력: 3
4. Call Stack 비었음
5. 이벤트 루프가 Callback Queue 확인 → 콜백 발견
6. 콜백을 Call Stack에 올림 → 출력: 2
이벤트 루프의 역할
while (true) {
if (callStack.isEmpty() && callbackQueue.hasTask()) {
callStack.push(callbackQueue.dequeue());
}
}
"Call Stack이 비면 Callback Queue에서 꺼내서 실행" — 이걸 무한 반복합니다.
Microtask vs Macrotask
console.log("1");
setTimeout(() => console.log("2"), 0); // Macrotask
Promise.resolve().then(() => console.log("3")); // Microtask
console.log("4");
출력: 1 → 4 → 3 → 2
| Microtask | Macrotask | |
|---|---|---|
| 예시 | Promise, async/await | setTimeout, setInterval |
| 우선순위 | 높음 | 낮음 |
Microtask가 먼저 전부 처리된 후 Macrotask가 실행됩니다.
정리
| 개념 | 설명 |
|---|---|
| Call Stack | 현재 실행 중인 함수 |
| Web APIs | 비동기 작업 처리 (별도 공간) |
| Callback Queue | 완료된 콜백 대기열 |
| Event Loop | Stack 비면 Queue에서 꺼내 실행 |