🔁

Node.js 이벤트 루프 — 브라우저와 다른 6단계 페이즈

timers → pending → idle → poll → check → close, 그리고 process.nextTick의 위치

브라우저의 이벤트 루프는 단순하다 — Task Queue + Microtask Queue. Node.js는 libuv 기반으로 6개 페이즈를 순회한다.

6개 페이즈

   ┌───────────────────────────┐
┌─>│        timers             │ ← setTimeout, setInterval
│  └─────────────┬─────────────┘
│  ┌─────────────┴─────────────┐
│  │     pending callbacks     │ ← 이전 루프에서 지연된 I/O 콜백
│  └─────────────┬─────────────┘
│  ┌─────────────┴─────────────┐
│  │       idle, prepare       │ ← (내부 전용)
│  └─────────────┬─────────────┘
│  ┌─────────────┴─────────────┐
│  │           poll            │ ← 새 I/O 이벤트 대기, I/O 콜백 실행
│  └─────────────┬─────────────┘
│  ┌─────────────┴─────────────┐
│  │          check            │ ← setImmediate
│  └─────────────┬─────────────┘
│  ┌─────────────┴─────────────┐
└──┤     close callbacks       │ ← socket.on('close')
   └───────────────────────────┘

setTimeout vs setImmediate

setTimeout(() => console.log('timeout'), 0);
setImmediate(() => console.log('immediate'));
// 순서가 매번 다를 수 있다! (timers 페이즈 진입 시점에 따라)

// 하지만 I/O 콜백 안에서는:
fs.readFile('file', () => {
  setTimeout(() => console.log('timeout'), 0);
  setImmediate(() => console.log('immediate'));
  // 항상 immediate가 먼저 — poll → check 순서이므로
});

process.nextTick

모든 페이즈 전환 사이에 실행된다. Microtask보다도 먼저. 남용하면 이벤트 루프가 다음 페이즈로 못 넘어간다.

우선순위: process.nextTick > Promise.then > setTimeout/setImmediate

핵심 포인트

1

Node.js 이벤트 루프는 6개 페이즈를 순회 (libuv)

2

setTimeout은 timers, setImmediate은 check 페이즈에서 실행

3

I/O 콜백 안에서는 setImmediate이 항상 setTimeout보다 먼저

4

process.nextTick은 모든 페이즈 전환 사이에 실행 — 최우선 순위

사용 사례

서버 성능 튜닝 — setImmediate로 I/O 처리 후 즉시 콜백 실행 nextTick vs setImmediate 선택 — nextTick은 긴급, setImmediate은 양보