이벤트 루프(Event Loop)는 이벤트와 콜백을 큐에서 꺼내 실행하는 단일 스레드 비동기 처리 모델이다. Node.js와 브라우저 JavaScript의 핵심 메커니즘이며, 블로킹 없이 수천 개의 동시 연결을 처리한다.
구조
Call Stack Task Queue Microtask Queue
┌────────┐ ┌────────┐ ┌────────────┐
│ main() │ │setTimeout│ │ Promise.then│
│ fn() │ │ callback │ │ async/await │
└────────┘ └────────┘ └────────────┘
↑ ↑ (Call Stack 비면 처리)
이벤트 루프: Call Stack이 비면 Microtask Queue → Task Queue 순으로 실행
동작 순서
javascript
console.log('1'); // 동기 (즉시)
setTimeout(() => {
console.log('4'); // Task Queue (마지막)
}, 0);
Promise.resolve().then(() => {
console.log('3'); // Microtask Queue (setTimeout보다 먼저)
});
console.log('2'); // 동기 (즉시)
// 출력: 1 → 2 → 3 → 4
Node.js 이벤트 루프 단계
┌────────────────────────────────────────┐
│ timers │ ← setTimeout, setInterval
├────────────────────────────────────────┤
│ pending callbacks │
├────────────────────────────────────────┤
│ idle, prepare │
├────────────────────────────────────────┤
│ poll │ ← I/O 이벤트 대기
├────────────────────────────────────────┤
│ check │ ← setImmediate
├────────────────────────────────────────┤
│ close callbacks │
└────────────────────────────────────────┘
매 단계 전후: Microtask 처리 (Promise, queueMicrotask)
블로킹 이벤트 루프 주의
javascript
// 나쁜 예: 동기 작업이 루프를 블로킹
app.get('/slow', (req, res) => {
const result = heavyCpuWork(); // 1초 소요 → 다른 요청 처리 불가
res.json(result);
});
// 좋은 예: Worker Thread나 비동기로 처리
app.get('/fast', async (req, res) => {
const result = await asyncCpuWork(); // 루프 해방
res.json(result);
});
관련 개념
- •비동기 I/O — 이벤트 루프의 기반
- •코루틴 — 협력적 멀티태스킹 구현
- •Promise — 이벤트 루프의 Microtask
- •동시성 — 이벤트 루프가 달성하는 목표