Event Loop 가이드: 자바스크립트 비동기가 실제로 돌아가는 방식
Dev

Event Loop 가이드: 자바스크립트 비동기가 실제로 돌아가는 방식


자바스크립트 비동기를 공부하다 보면 결국 event loop를 만나게 됩니다. Promise, setTimeout, async/await를 어느 정도 써도, 왜 어떤 코드는 바로 실행되고 어떤 코드는 나중에 실행되는지 헷갈릴 때가 많습니다.

이때 event loop 개념을 잡아두면 “자바스크립트가 한 번에 하나씩 실행되는 것 같은데도 어떻게 비동기가 가능하지?”라는 질문이 풀리기 시작합니다.

이 글에서는 아래 내용을 정리합니다.

  • event loop가 무엇인지
  • call stack, queue 가 어떤 역할을 하는지
  • 왜 비동기 코드는 나중에 실행되는 것처럼 보이는지

핵심은 event loop는 비동기 작업 완료 후 실행할 콜백과 작업들을 적절한 시점에 call stack 으로 올려 주는 실행 조정 메커니즘이라는 점입니다.

Event Loop 를 왜 알아야 할까

자바스크립트는 기본적으로 한 시점에 하나의 실행 흐름을 따라가는 언어처럼 보입니다. 그런데도:

  • setTimeout
  • 클릭 이벤트
  • 네트워크 응답 처리
  • Promise 후속 처리

같은 일이 동시에 돌아가는 것처럼 보입니다.

이런 동작을 이해하려면 event loop를 알아야 합니다.

가장 기본적인 구성

입문 단계에서는 아래 세 가지를 먼저 잡으면 됩니다.

  • call stack
  • queue
  • event loop

1. Call Stack

지금 실행 중인 함수들이 쌓이는 곳입니다. 자바스크립트는 보통 이 스택의 맨 위 함수를 실행합니다.

2. Queue

나중에 실행될 작업들이 대기하는 곳입니다. 타이머 완료, 이벤트 발생, Promise 후속 처리 같은 것들이 여기에 들어갈 수 있습니다.

3. Event Loop

call stack 이 비었는지 보고, queue 에 대기 중인 작업을 stack 으로 올리는 역할을 합니다.

즉, event loop는 “언제 다음 작업을 실행할지”를 계속 확인하는 조정자처럼 생각하면 됩니다.

간단한 예시

console.log('A');

setTimeout(() => {
  console.log('B');
}, 0);

console.log('C');

많은 입문자가 A, B, C 순서를 예상하지만 실제로는 보통:

A
C
B

처럼 보입니다.

이유는 setTimeout의 콜백이 바로 stack 에 들어가는 것이 아니라, 타이머가 끝난 뒤 queue 로 가고, 그 다음 call stack 이 비었을 때 event loop 에 의해 실행되기 때문입니다.

Promise 는 왜 또 다르게 보일까

Promise.then() 이나 await 뒤의 후속 코드는 보통 일반 타이머 콜백보다 먼저 처리되는 것처럼 보일 때가 있습니다. 이 부분은 microtask/macrotask 구분까지 들어가면 더 정확해지지만, 입문 단계에서는 “queue 도 종류가 있고 우선순위가 다를 수 있다” 정도로 이해해도 충분합니다.

예를 들어:

console.log('start');

setTimeout(() => console.log('timeout'), 0);

Promise.resolve().then(() => console.log('promise'));

console.log('end');

보통 결과는:

start
end
promise
timeout

처럼 보입니다.

즉, 비동기라고 다 같은 타이밍으로 실행되는 것은 아닙니다.

async/await 와 event loop

await를 만나면 함수 실행은 잠시 중단되고, 나머지 후속 흐름은 Promise 기반 비동기 처리로 이어집니다. 그래서 await 뒤 코드는 “지금 당장 stack 에서 이어서 실행”된다기보다, 나중에 이어지는 흐름으로 이해하는 편이 맞습니다.

이 점 때문에 async/await는 동기처럼 보여도 실제 실행 타이밍은 event loop 와 Promise 처리 구조에 영향을 받습니다.

자주 하는 오해

1. setTimeout(fn, 0) 이면 바로 실행된다

아닙니다. “최소한 지금 call stack 이 끝난 뒤”에 실행된다고 이해하는 편이 맞습니다.

2. event loop 가 모든 비동기 작업을 직접 실행한다

정확히는 실행 시점을 조정하고, 적절한 작업을 stack 으로 올리는 흐름을 담당한다고 보는 편이 좋습니다.

3. async/await 를 쓰면 event loop 를 몰라도 된다

가독성은 좋아지지만, 실행 순서를 이해하려면 결국 event loop 개념이 필요합니다.

처음 공부할 때 추천하는 실습

  1. console.log, setTimeout 조합 예제 실행하기
  2. Promise 예제를 추가해서 순서 비교하기
  3. 같은 흐름을 async/await로 바꿔 보기
  4. 예상한 실행 순서와 실제 순서를 비교하기

이 과정을 직접 해 보면 event loop는 이론보다 체감으로 훨씬 빨리 이해됩니다.

FAQ

Q. event loop 는 브라우저에만 있나요?

아닙니다. Node.js 같은 런타임에서도 중요한 개념입니다.

Q. Promise 와 setTimeout 은 왜 순서가 다르게 보이나요?

대기열 종류와 처리 우선순위 차이 때문입니다.

Q. event loop 를 완벽히 알아야 비동기 코드를 쓸 수 있나요?

처음부터 완벽할 필요는 없지만, 실행 순서가 헷갈릴 때는 꼭 도움이 됩니다.

먼저 읽어볼 가이드

검색 유입이 많은 핵심 글부터 이어서 보세요.