자바스크립트 런타임과 엔진의 차이: 이벤트 루프는 어디에 있을까
자바스크립트 엔진? 런타임? 이 두 용어의 차이에 대해 햇갈리시는 분이 계실겁니다. 이 글에서는 자바스크립트의 엔진과 런타임을 비교해보고 이벤트 루프의 역할, 추상적 구조를 살펴보겠습니다.

1. 엔진
- 역할
- ECMAScript(ECMA-262 표준)코드를 파싱하고 실행한다.
- 메모리 관리, 가비지 컬렉션을 수행한다.
- 구성요소
- 파서: 소스 코드를 AST(Abstract Syntax Tree)로 변환.
- 컴파일러: AST를 최적화된 바이트코드 또는 네이티브 코드로 컴파일.
- 가상 머신 (VM): 컴파일된 코드를 실행. JIT(Just-In-Time) 컴파일링을 통해 성능 최적화.
- 주요 엔진
- V8: Google Chrome, Node.js에 사용
- SpiderMonkey: Mozilla Firefox에 사용
- JavaScriptCore: Safari 및 iOS에서 사용
- V8 엔진
- V8은 구글이 개발한 자바스크립트 엔진으로, 자바스크립트 코드를 컴파일하고 실행하는 역할을 합니다.
- V8은 단일 스레드에서 동작하며, 자바스크립트 코드를 해석하고 실행합니다.
- 메모리 관리와 가비지 컬렉션도 V8의 책임입니다.
- V8은 단순히 자바스크립트 코드의 실행을 처리하는 엔진일 뿐, 비동기 작업이나 이벤트 루프를 관리하지는 않습니다.
2. 런타임
- 역할
- 엔진을 포함한 ECMAScript 실행 환경을 제공한다.
- 플랫폼에 따라 추가적인 비표준 API(DOM, fs)를 제공한다.
- 구성요소
- 엔진: ECMAScript 실행 담당
- 이벤트 루프: 비동기 작업을 관리, 콜백 함수 실행 순서 제어
- 호스트 API: 브라우저의 DOM API, 서버의 파일 시스템 API 등 추가 기능 제공
- 주요 런타임
- 브라우저: DOM, BOM, fetch API 등 웹 관련 API 제공
- Node.js: 파일 시스템, 네트워크 I/O, 프로세스 관리 등 서버 관련 API 제공
- Deno/Bun: Node.js와 유사하지만 파일 시스템, 보안 모델 등에서 차별화된 API 제공
3. 이벤트 루프는 어디에 포함되어 있는가?
- Node.js 환경
- Node.js는 libuv라는 라이브러리를 사용하여 이벤트 루프를 관리합니다. Node.js의 이벤트 루프는 파일 I/O, 네트워크, 타이머, 비동기 작업을 관리하며, 작업이 완료되면 V8에서 해당 작업의 콜백을 실행하게 됩니다.
- 브라우저 환경
- HTML 명세의 이벤트 루프 스펙을 따르지만, 구체적인 구현은 각자 다릅니다.
- 이벤트 루프 관리를 위한 별도의 공개된 라이브러리를 사용하지 않습니다.
- 내부 구현이 브라우저 코드에 긴밀하게 통합되어 있어, Node.js처럼 명확하게 분리된 모듈로 존재하지 않습니다.
- 각 브라우저가 자체적으로 구현하고 있고, 그 구현이 브라우저 코드에 깊이 통합되어 있습니다.
즉, 이벤트 루프는 자바스크립트 런타임(브라우저, Node.js 등)이 제공하는 기능이고, 자바스크립트 엔진(V8)은 이벤트 루프에서 푸쉬한 콜백을 실행하는 역할을 합니다.
4. 이벤트루프의 구조
flowchart TB
subgraph ELS["Event Loop System (ELS)"]
subgraph TQ["Task Queue (TQ)"]
setTimeout["setTimeout"]
setInterval["setInterval"]
IO["I/O Operations (File, Network)"]
XHR["XHR Requests (Ajax, Fetch)"]
UIEvents["UI Events (Click, Keypress)"]
end
subgraph JQ["Job Queue (JQ)"]
subgraph MQJ["Microtask Queue (MQJ)"]
PromiseThen["Promise.then()"]
AsyncAwait["async/await"]
MutationObserver["MutationObserver"]
QueueMicrotask["queueMicrotask()"]
end
end
subgraph RQ["Render Queue (RQ)"]
Layout["Layout Calculation"]
Paint["Paint (Rasterization)"]
Composite["Compositing"]
StyleRecalc["Style Recalculation"]
CSSAnimation["CSS Animation"]
Transition["CSS Transition"]
end
end
- 전체 이벤트 루프 시스템을 표현하는 집합
- Event Loop System, ELS = { Task Queue, Microtask Queue, Render Queue }
- Task Queue: 넓은 의미에서 비동기 작업의 완료 후 실행될 일반적인 태스크들, 콜백들이 대기하는 큐
- TQ = { setTimeout, setInterval, I/O, XHR Requests 등 }
- 특정 이벤트(네트워크 응답, 사용자 인터페이스 이벤트 등)를 처리하는 비동기 작업을 기다리는 대기열
- TQ ⊆ Message Queue
- Microtask Queue: 즉시 처리되어야 하는 짧은 작업들이 들어가는 큐
- MQ = { Promise.then(), async/await, MutationObserver 등 }
- MQ ⊆ Job Queue (JQ)
- Render Queue: 브라우저 렌더링 작업이 들어가는 큐
- RQ = { 렌더링, 스타일 변경 }
한마디로 정리하면 아래와 같습니다.
- Event Loop System (ELS) = { TQ, JQ = { MQ }, RQ }
- Microtask Queue는 Job Queue의 부분집합
- 이 모든 큐들은 이벤트 루프 시스템 내에서 서로 역할을 분담합니다.