이벤트 루프

싱글 스레드 환경에서 비동기 작업을 처리하는 메커니즘입니다. 주로 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

MicrotaskMacrotask
예시Promise, async/awaitsetTimeout, setInterval
우선순위높음낮음

Microtask가 먼저 전부 처리된 후 Macrotask가 실행됩니다.


정리

개념설명
Call Stack현재 실행 중인 함수
Web APIs비동기 작업 처리 (별도 공간)
Callback Queue완료된 콜백 대기열
Event LoopStack 비면 Queue에서 꺼내 실행

CSLOG에서 보기