도대체 이벤트 루프(event loop)가 뭐야??

#들어가기

Javascript로 개발을 하다보면 event loop라는 용어를 심심치 않게 접하게 됩니다. event loop가 도대체 뭐길래 javascript 관련해 글을 읽다보면 event loop가 자주 나오는 걸까요?

#이벤트 루프(event loop)


Javascript의 Runtime의 구조를 크게 보면 메모리 할당과 관련 있는 heap과 Stack frame이 저장되는 stack이 있습니다. 하지만 런타임 그 자체로 보면 그 내부의 우리가 javascript를 사용하면서 자주 쓰는 setTimeout이나 DOM 또는 Http Request를 찾아볼 수 없습니다.


Javascript Runtime을 포함한 좀 더 큰 그림으로 구조를 살펴보겠습니다. 브라우저가 제공하는 web APIs와 Callback queue, Event loop를 확인할 수 있습니다.

자바스크립트의 큰 특징 중 하나는 ‘single thread’ 기반의 언어라는 점입니다. 스레드가 하나라는 말은 동시에 하나의 작업만을 처리할 수 있다라는 소리와 같고, 또 구조에서 볼수 있듯이 하나의 call stack을 가지고 있다는 소리와 같습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function multiply(x, y) {
return x*y;
}

function square(n) {
return multiply(n, n);
}

function printS(n) {
var s = square(n);
console.log(s);
}

printS(4);

간단한 코드로 스택의 변화를 보면 printS(4)를 하기위해 stack 밑에서부터 printS(4), square(n), multiply(x, y) 순으로 쌓이게 됩니다.

만약 stack에 쌓이는 함수들 중 엄청난 시간을 필요로 하는 함수가 stack에 push되면 어떻게 될까요? single thread 기반의 javascript는 그 함수가 끝날때 까지 아무것도 하지 못하는 치명적인 문제가 발생할겁니다. 즉, browser 측면에서 보면 stack에 있는 함수 때문에 browser가 동작하지 않는 문제가 발생합니다.

다음과 같은 문제를 해결하기 위해 javascript는 callback를 사용합니다.

1
2
3
4
5
6
7
console.log("hi");

setTimeout(function() {
console.log("i am in time-out");
},5000);

console.log("end");

위의 코드를 실행해보면 ‘hi’, ‘end’가 출력된 뒤 5초정도 후 ‘i am in time-out’이 출력되는 것을 확인할 수 있습니다. 그럼 위와 같은 코드가 앞서 확인한 스택과 어떻게 동작할까요??

먼저 stack에는 console.log(“hi”)가 들어가 ‘hi’를 출력한 뒤 stack을 빠져 나갑니다. 다음 setTimeout()함수가 stack에 push 됩니다. 하지만 5초뒤에 작동할 함수를 위해 stack에 넣어 둘수는 없습니다. 그렇게 되면 모든 함수가 기다려야 하는 문제가 발생합니다. 즉 이런 상황에서는 stack에 넣지 않고 따로 처리를 합니다. stack을 계속 보면 console.log(“end”)가 push 되고 ‘end’를 출력합니다. 그리고 5초 뒤 다시 stack에 console.log(“i am in time-out”)가 push 되어집니다. 어떻게 동작하는 걸까요?

여기서 event loop가 등장합니다. 앞서 javascript 구조를 큰 그림으로 볼때 web APIs라는 것을 볼 수 있었습니다.

setTimeout의 콜백함수는 web APIs로 보내지고 setTimeout은 stack에서 빠져나오게 됩니다. web APIs의 timer가 5초가 지난 뒤 작업이 끝나면 콜백을 다시 task queue 또는 callback queue로 보냅니다.

마침내 event loop가 stack이 비워져 있는지 확인한 뒤 stack으로 callback을 보냅니다.

event loop가 하는 일은 간단합니다. queue의 첫번째 있는 작업을 stack이 비워져있는지 확인한 뒤 작업을 stack으로 보내는 역할을 합니다.

1
2
3
4
5
6
7
console.log("1");

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

console.log("3");

그럼 이제 다음과 같은 코드에서 왜 1 3 2로 출력되는지도 알수 있습니다. event loop가 스택이 비워져 있는 상태인지 확인을 하기 때문에 1 3 2로 출력되는 것 입니다. 즉, stack이 비워져 있지 않은 상태라면 event loop는 queue에 있는 작업을 stack으로 보내지 않고 기다립니다.

#마치며

부족한 설명이었지만 이 글을 통해 javascript event loop의 대해서 조금이라도 이해하는 기회가 되었으면 좋겠습니다.

설명 도중 틀린 설명이 있다면 코멘트로 남겨주세요. 수정하겠습니다!!

#참조

Philip Roberts: What the heck is the event loop anyway? | JSConf EU 2014

Share