이벤트 루프를 설명하기 앞서 자바스크립트의 특징부터 가볍게 보고가도록 하겠습니다.
자바 스크립트는 단일 스레드 기반의 언어로 한 번에 하나의 작업만을 처리할 수 있다.
비동기로 동작하기 때문에 단일 스레드임에도 불구하고 동시에 많은 작업을 수행한다.
하지만 비동기로 동작하는 핵심 요소는 자바스크립트가 아닌 브라우저가 가지고 있다.(Node의 경우 libuv 라이브러리)
Heap : 메모리 할당이 발생하는 곳
Call Stack : 실행된 코드의 환경을 저장하는 자료구조로, 함수 호출 시 이곳에 저장된다. 어떤 함수를 저장하면 스택에 쌓고 또 다른 함수를 호출하면 그 다음 스택에 쌓이면서 가장 위에 쌓인 함수를 가장 먼저 처리한다. LIFO(Last In First Out)
Web APIs : Web API는 브라우저에서 제공하는 API로 DOM, Ajax, TimeOut 등이 있다.
CallStack에서 실행된 비동기 함수는 Web API를 호출하고, Web API는 콜백 함수를 Task Queue에 넣는다.
Callback Queue : 함수를 저장하는 자료구조로, Call Stack과 다르게 가장 먼저 들어온 함수를 가장 먼저 처리한다.
Event Loop : 이벤트 루프는 call stack이 다 비워지면 callback queue에 존재하는 함수를 하나씩 call stack으로 옮기는 역할을 한다.
function main(){
console.log('First');
setTimeout(
function display(){ console.log('Second'); }
,0);
console.log('Third');
}
main();
// Output
// First
// Third
// Second
'First'와 'Third' 2개의 console.log와 그 사이에 0ms 의 대기 시간으로 콘솔에 'Second'를 보여주는 setTimeout함수가 끼워져 있습니다.
결과값을 보게 되면 First => Second => Third 순서가 아닌 First => Third => Second 순서로 나오게 되는데 아래 그림과 함께 살펴보도록 하겠습니다.
main 함수에 대한 호출이 먼저 call stack에 추가(push)됩니다. 그런 다음 브라우저는 main 함수의 첫 번째 명령문인 console.log('First')를 스택으로 추가됩니다. console.log('First')가 실행되어 화면에 출력한 뒤, call stack에서 제거됩니다.
다음 명령문인 setTimeout이 call stack에 추가되고 실행이 되면서 브라우저가 제공하는 timer Web API를 호출한 후에 call stack 에서 제거됩니다.
console.log('Third')는 브라우저에서 timer가 실행되는 동안 스택에 추가가 되며 이 경우 0ms 의 시간만큼 지연이 되기 때문에 브라우저에서 콜백을 수신하는 즉시 메시지 대기열에 콜백이 추가됩니다.
main함수에서 마지막 명령문이 실행된 후 main 함수가 call stack 튀어나와 call stack 이 비어있게 됩니다. 브라우저가 대기열인 message queue 에서 call stack 으로 메시지를 추가하려면 먼저 call stack이 비워있어야 합니다. 바로 이것 때문에 setTimeout에서 제공된 지연시간이 0ms임에도 다른 모든 것들이 실행이 완려될 때까지 기다려야 하는 이유입니다.
이제 콜백이 call stack으로 추가되어 실행이 됩니다. console.log('Second')가 실행이 되며 이것이 자바스크립트의 이벤트 루프 입니다.
참고자료
JavaScript Event Loop Explained
자바스크립트 비동기 핵심 Event Loop 정리
What the heck is the event loop anyway?
내일 프론트엔드 면접이라 CS 지식 급하게 공부중이었는데, 이 포스팅 덕분에 자바스크립트 이벤트 루프를 확실히 이해할 수 있었네요. 유익한 포스팅 감사합니다!