본문 바로가기
Frontend/Javascript

Javascript - 이벤트 루프

by 취업하고싶다! 2025. 1. 13.

 

 

 

Event Loop란?

 

단일 스레드에서 실행되는 비동기 작업을 처리하는 메커니즘

이벤트 루프는 Call stack, Micro task queue, Macro task queue로 구성

 

 

JS Engine

자바스크립트 엔진은 Memory Heap  Call Stack 으로 구성되어 있다.(그림의 왼쪽 영역)
가장 유명한 것이 구글의 V8 Engine이다.
자바스크립트는 단일 스레드 프로그래밍 언어인데, 이는 Call Stack이 하나 라는 의미이다.
(멀티가 되지 않고, 하나씩 하나씩 처리한다는 의미!)

  • Memory Heap : 메모리 할당이 일어나는 곳
    (ex, 우리가 프로그램에 선언한 변수, 함수 등이 담겨져 있음)
  • Call Stack : 코드가 실행될 때 쌓이는 곳. stack 형태로 쌓임
    • Stack(스택) : 자료구조 중 하나, 선입후출(LIFO, Last In First Out)의 룰을 따른다.

 

Web API

그림의 오른쪽에 있는 Wep API는 JS Engine의 밖에 그려져 있다.
즉, 자바스크립트 엔진이 아니다.
Web API  브라우저에서 제공하는 API 로, DOM, Ajax, Timeout 등이 있다.
Call Stack에서 실행된 비동기 함수는 Web API를 호출하고,
Web API는 콜백함수를 Callback Queue에 밀어 넣는다.

 

 

Callback Queue

비동기적으로 실행된 콜백함수가 보관 되는 영역
예를 들어 setTimeout에서 타이머 완료 후 실행되는 함수(1st 인자),
addEventListener에서 click 이벤트가 발생했을 때 실행되는 함수(2nd 인자) 등이 보관된다.

  • Queue(큐) : 자료 구조 중 하나, 선입선출(FIFO, Frist In Frist OUT)의 룰을 따른다.

 

 

Event Loop

Event Loop는 Call Stack과 Callback Queue의 상태를 체크하여,
Call Stack이 빈 상태가 되면, Callback Queue의 첫번째 콜백을 Call Stack으로 밀어넣는다.
이러한 반복적인 행동을 틱(tick) 이라 부른다.

 

정리하면,
V8 엔진에서 코드가 실행되면, Call Stack에 쌓인다.
Stack의 선입후출 룰에 따라 제일 마지막에 들어온 함수가 먼저 실행되며, Stack에 쌓여진 함수가 모두 실행된다.
비동기 함수가 실행된다면, Web API가 호출된다.
Web API는 비동기함수의 콜백함수를 Callback Queue에 밀어넣는다.
Event Loop는 Call Stack이 빈 상태가 되면Callback Queue에 있는 첫번째 콜백을 Call Stack으로 이동시킨다.
(이러한 반복적인 행동을 틱(tick)이라 한다.)

 

자바스크립트를 단일 스레드 프로그래밍 언어라 한번에 하나씩 밖에 실행할 수 없다.
그러나 Web API, Callback Queue, Event Loop 덕분에 멀티 스레드 처럼 보여진다.
 

 

 

Microtask queue

console.log('script start'); 

setTimeout(function() {
  console.log('setTimeout');
}, 0);

Promise.resolve().then(function() {
  console.log('promise1');
}).then(function() {
  console.log('promise2');
});

console.log('script end');

 

위 코드는 콘솔창에서 다음 순서대로 실행된다.

script start
script end
promise1
promise2
setTimeout

 

script start, script end 순으로 처리되는건 당연한데, 왜 Promise, setTimeout 순으로 실행되는 걸까?

여기서 Microtask Queue의 개념이 나온다.

 

Event Loop는 우선적으로 Microtask Queue를 확인한다.
만약 Microtask Queue에 콜백이 있다면, 이를 먼저 Call Stack에 담는다.
그리고 Microtask Queue에 더이상 처리해야할 콜백이 없다면,
Task Queue에 확인 후 처리한다.

 

Promise의 then()의 콜백은 Task Queue가 아닌 Microtask Queue 에 담긴다.
따라서 위 코드에서는 우선순위가 높은 Microtask Queue부터 처리되므로,
Promise의 then() 콜백이 다 실행되고, setTimeout 콜백이 실행되는 구조이다.

 

 

Microtask queue에는 Promise, async/await 과 같은 작업들이 들어가고 Macrotask queue에는 Web API (setInterval, setTimeout)와 같은 작업들이 들어간다.

이벤트 루프는 Call stack을 확인하고 Call stack이 비어있는 경우 Micro task queue의 작업을 Call stack으로 옮긴다. 그리고 Micro task queue가 비어있는 경우, Macro task queue의 작업을 Call stack으로 옮기고 처리한다.

'Frontend > Javascript' 카테고리의 다른 글

Javascript - 얕은 복사, 깊은 복사  (0) 2025.01.14
Javascript - 데이터 타입  (0) 2025.01.02
Javascript - 변수  (0) 2025.01.02
Javascript - Scope, Closure  (0) 2024.12.23
Javascript - 이벤트 버블링, 캡쳐링  (0) 2024.12.23