본문 바로가기
CS 질문

[Deep Dive CS- Q1] Javascript Run-to-completion, Event Loop

by 민챙이_99 2025. 12. 15.

Q1. 자바스크립트는 'Single Thread' 기반 언어임에도 불구하고, 어떻게 브라우저에서 네트워크 요청이나 사용자 입력을 Non-blocking(비동기)'으로 처리할 수 있는지, 'Run-to-completion' 개념과 Event Loop의 역할을 중심으로 설명해주세요. 

- Run-to-completion : 실행 완료 보장" 또는 "완주 보장". 즉, 하나의 함수(태스크)가 실행되면, 그 함수가 완전히 종료될 때까지 어떤 작업도 끼어들(Intterupt) 수 없다. 

- 싱글 스레드 = 콜스택이 1개

 

=> 이게 가능한 이유는 "자바스크립트 엔진(V8)싱글스레드이지만, 브라우저멀티 스레드" 이기 때문입니다. 

 

javascript는 기본적으로 한줄을 실행하게 되면 그 실행 한줄이 콜스택에 적재되어 실행됩니다. 이때 실행해야 하는 코드가 네트워크 요청이나 사용자 입력이라면 해당 부분은 Web API에게 요청합니다. 

 

*Web API란? 브라우저가 제공하는 API로, 자바스크립트 엔진 외부에서 비동기 작업을 수행할 수 있도록 돕습니다. (예: setTimeout, fetch, DOM Events 등)
Tip: MDN 문서(https://developer.mozilla.org/ko/docs/Web/API) 수많은 API가 있지만, 실무에서는 자주 쓰이는 것 위주로 자연스럽게 익히게 됩니다. 😀

 

Web API에서 이를 완료하면 Callback Queue에 담습니다.

Callback Queue에는 우선순위가 다른 여러 개의 대기열이 존재합니다. 

 

[Callback Queue] (*순서가 높을 수록 우선순위가 높음)

1. Microtask Queue : Promise.then, MutationObserver (콜스택이 비워지면 제일 먼저 실행됨)
2. Animation Frames : requestAnimationFrame (브라우저가 화면을 그리기(Repaint) 직전에 실행)
3. Task Queue (Macrotask Queue) : setTimeout, setInterval (Microtask가 완전히 처리된 후에야 이벤트 루프에 의해 실행될 기회를 얻습니다)

 

Callback Queue는 바구니라면, 이걸 실행시키 위해서 콜스택에 누구를 보낼지 결정하는 'Event Loop'가 있습니다. 
Event Loop는 Run-to-completion 원칙을 지키기 위해서 존재합니다. 이벤트 루프는 끊임없이 현재 콜스택이 비어있는지를 확인해서 비어있으면, 바구니에 담긴(Callback Queue) 태스크들을 우선순위에 따라서 하나씩 꺼내어 스택으로 올려 보냅니다. 

 

자바스크립트가 Run-to-completion(하나의 함수가 끝날 때까지 멈추지 않음) 특성을 가지기 때문에, 비동기 작업은 당장 실행되지 못하고 대기열(Queue)에서 기다렸다가 나중에 실행되는 것입니다.

+ task queus는 set(집합)이라고 한다. (큐 아님, 단 Microtask Queue는 진짜 큐 라고 한다. )

 

이유에 대해서 간단히 살펴보자면, 이벤트 루프 처리 모델은 '실행 가능한 태스크'를 가져오는 방식 이기 때문이라고 한다. 

예를 들어서, setTimeout 100개가 들어오고, 클릭 이벤트가 들어오면, 
IF 큐, setTimeout 100개를 모두 처리하고 나서 클릭 이벤트를 처리할 수 있다. (큐는 FIFO 니까)
그래서 성능과 사용자 경험을 위해서 여러 종류의 대기열이 존재하는 형태이다. 

 

 

출처 ) https://medium.com/@burak.bburuk/what-is-the-event-loop-in-javascript-and-why-is-it-essential-to-understand-b11af520a28b

https://html.spec.whatwg.org/multipage/webappapis.html#event-loops