이벤트 루프 (Event Loop)

728x90
반응형

 

자바스크립트는 단일 스레드 언어이다. 

 

단일 스레드는 동시에 하나의 작업만 처리할 수 있다. 

 

 

 

하지만 실제 자바스크립트는 여러 개의 HTTP 요청을 날리기도 하고,

 

마우스 클릭과 같은 이벤트, 애니메이션 효과 등 여러 개의 작업을 동시에 한다.

 

이렇게 동시성과 비동기를 처리할 수 있는 이유는

 

브라우저나 Node.js 처럼 자바스크립트 엔진을 구동하는 환경 덕분이다. 

 

 

 

 

ECMAScript에는 이벤트 루프에 대한 내용이 없다

(참고: meetup.toast.com/posts/89)

 

V8 과 같은 자바스크립트 엔진은 단일 호출 스택 (콜스택)을 사용하며 해당 요청을 순차적으로 스택에 넣어 처리한다.

 

아래 그림에서 js안에 콜스택이라고 써진 부분이다. 일반 함수 처리는 여기서 처리한다.

이벤트 루프의 모습이다. 밑에서 다시 살펴볼 것이다.

출처: https://blog.sessionstack.com/how-does-javascript-actually-work-part-1-b0bacc073cf

 

 

 비동기 호출에 해당하는 setTimeOut이나 XMLHttpRequest 같은 함수는 Web API영역에 정의되어 있다. 

 

setTimeOut에 전달되는 콜백함수가 web API에서 처리된다.

 

 

setTimeOut(console.log('11'),0);

console.log('222');

 

위의 경우 코드가 적힌 순서는 11 1 => 222 지만 실제로는 222 => 111 순으로 출력이 된다.

 

 

setTimeOut함수는 web API에서 처리되어 0초(혹은 정의한 ms초 후)에 콜백 큐에 

 

콜백함수인 console.log(111);를 콜백 큐(tastk queue)로 전달한다. 콜백큐는 이벤트 큐라고도 불린다.

 

 스택과 달리 큐 형태라서 선입선출로 먼저 들어온 것이 처리된다. 

 

 

이벤트 루프는 지속적으로 돌며 콜 스택과 콜백 큐를 검사하고 콜 스택이 비워져있는 것을 확인하면

 

콜백 큐에서 콜백 함수를 하나씩 가져다 실행한다. 이렇게 반복하는 행동을 틱 tick이라고 한다.

 

 

 

 

위에서 setTimeout(콜백함수, 0); 이렇게 0초를 지정해줬는데, 실제로 0초 후에 실행되는 것을 보장하지는 못한다.

 

사실은 0초 후에 콜백 큐에 함수를 넣는 것을 보장한다. 

 

만약 콜 스택이 비워져있지 않다면 0초 후에 실행되는 것을 보장할 수 없을 것이다. (자주 등장하는 주제다)

 

 

 

마이크로 태스크큐는 뭔데(?) (다르다는 말도 있지만 잡큐라고 불리기도 한다.)

 

 이벤트 루프의 개념은 HTML 스펙에 정의되어 있다. 근데 마이크로 태스크라는 것도 있다고 한다.

 

이건 뭐지? 프로미스와 다른 비동기 함수를 동시에 실행시켜보자!

 

 

setTimeout(function() { // (A)
    console.log('A');
}, 0);
Promise.resolve().then(function() { // (B)
    console.log('B');
}).then(function() { // (C)
    console.log('C');
});

 

둘 다 비동기적으로 처리될 텐데 B => C => A의 순서로 실행이 된다. 

 

마이크로 태스크는 태스크 큐보다 우선순위를 갖는다. 즉 먼저 실행이 된다. 

 

A는 태스크 큐에 추가되고  B, C는 마이크로 태스크 큐에 추가가 된다. 별도로 처리되는 것이다.

 

 

즉, 이벤트 루프는 콜 스택이 비워지면 마이크로 태스크 큐가 비었는지 먼저 확인하고 그 다음 태스크 큐를 확인한다.

 

 

 

앗 이건 또 처음 보네요 Animation Frames가 있습니다.

requestAnimationFrame API가 실행되면 콜백이 Animation Frames으로 담긴다.

 

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

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

requestAnimationFrame(function() {
    console.log("requestAnimationFrame");
})

 

Microtask Queue > Animation Frames > Task Queue 순으로 실행된다

 

 

 

 

 

참고

meetup.toast.com/posts/89

velog.io/@thms200/Event-Loop-%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EB%A3%A8%ED%94%84

 

 

728x90
반응형
TAGS.

Comments