프로그래밍(Basic)/Javascript(TS,Node)

[바미] Javascript Micro task queue.

Bami 2022. 8. 8. 11:49
728x90
반응형

지난 시간엔 콜 스택, 태스크 큐, 이벤트 루프에 대해 알아보며 호출스택과 테스크큐의 관계에 대해 알아보았는데요.

 

[바미] 콜 스택, 태스크 큐, 이벤트 루프

안녕하세요. 오늘은 자바스크립트의 콜스택, 태스크 큐, 이벤트 루프가 무엇인지에 대해 알아보도록 하겠습니다. 먼저 자바스크립트는 단일 스레드입니다. 이 말의 뜻은 한 번에 1개의 작업만

codesk.tistory.com

오늘은 Micro task queue에 대해 알아보며 지난번에 했던 태스크 큐와 어떤 차이가 있는지 알아보도록 하겠습니다.

 

태스크 큐와 마이크로 태스크 큐

먼저 마이크로 태스크 큐는 일반 태스크 보다 좀 더 우선순위를 갖는 태스크 큐라고 보면 됩니다.

2개의 큐 모두 콜백함수가 들어간다는 점에서 동일하지만 어떤 함수를 실행하느냐에 따라 어디로 들어가는지가 달라지게 됩니다.

여기에 큐 (Queue)는 실제 우리가 아는 자료구조의 큐와는 다릅니다. 우선순위 큐 (Priority Queue) 라고 할 수 있는데,

이벤트 루프가 2개의 큐에서 태스크를 꺼내는 조건이 "제일 오래된 태스크" 이기 때문이죠.

 

태스크 큐는 마이크로 태스크 큐와 매크로 태스크 큐로 나누어지는데 어떤 API를 사용하냐에 따라 둘 중 하나를 사용하게 됩니다.

macrotasks - requestAnimationFrame, I/O, UI rendering, setTimeout, setInterval, setImmediate
microtasks - process.nextTick, Promise, queueMicrotask(f), MutationObserver

동작 형태는 아래와 같습니다.

/velog.io/@yejineee 참조.

우리에게 익숙한 함수인 Web API의 setTimeout() 의 콜백함수가 태스크 큐에 들어가고 Promise 의 콜백함수가 마이크로태스크 큐에 들어간다는 것을 알 습니다. 그렇다면 이벤트 루프는 각 콜백함수를 태스크/마이크로태스크 큐에서 꺼내쓰는 것인데, 그렇다면 어떤게 먼저일까요?

 

마이크로 태스크 큐가 먼저입니다.

이벤트 루프는 마이크로태스크 큐의 모든 태스크들을 처리한 다음, 태스크 큐의 태스크들을 처리하게 됩니다.

따라서, Promise 의 콜백함수가 setTimeout() 의 콜백함수보다 먼저 처리됩니다.

 

console.log('call stack!');
setTimeout(() => console.log('task queue!'), 0);
Promise.resolve().then(() => console.log('micro task queue!'));

결과

마이크로 태스트 큐의 콜백함수가 먼저 처리되는 것을 알 수 있습니다. 

console.log()는 처음 스크립트가 로드될 때 call stack!이라는 태스크가 먼저 태스크 큐에 들어가게 되고,

이벤트 루프가 태스크 큐에서 이 태스크를 가져와 실행하게 되는 것입니다.

그러니까 call stack에서는 이미 GEC(Global Execution Context)가 생성되어 있는 상태에서 call stack! 이라는 태스크를 실행하게 되면 그제서야 GEC에 속한 코드가 실행되는 방식인겁니다.

 

그럼 위 코드가 어떻게 동작하는 지 그림으로 살펴보도록 하겠습니다.

제일 먼저 "call stack!"이라는 태스크가 태스크 큐에 들어가게 됩니다.

그 후, 이벤트 루프가 그 태스크를 가져와서 로드된 스크립트를 실행시키게 되어 처음에 console.log()가 실행됩니다.

그 다음, setTimeout() 이 콜 스택으로 가고 브라우저가 이를 받아서 타이머를 동작시키게 됩니다.

타이머가 끝나면 setTimeout() 의 콜백함수를 태스크 큐에 넣어 줍니다.

그 다음 Promise 가 콜 스택으로 가고 콜백함수를 마이크로태스크 큐에 넣어 줍니다.

이벤트 루프는 마이크로태스크 큐에서 제일 오래된 태스크인 Promise 의 콜백함수를 가져와 콜 스택에 넣어 줍니다.

Promise 의 콜백함수가 끝나고 태스크 큐에서 제일 오래된 태스크인 setTimeout() 의 콜백함수를 가져와 콜 스택에 넣어줍니다.

setTimeout() 의 콜백함수가 끝나면 콜 스택이 비게 되고 프로그램이 종료됩니다.

 


지금까지 마이크로태스크가 무엇인지, 태스크 큐와 마이크로태스크가 어떻게 다른지, 이 들을 각각을 어떻게 처리하는지에 대해 알아보았습니다.이런 원리들을 이해하고 사용한다면 비동기 로직을 다룰 때 훨씬 견고하고 예측 가능한 코드를 짤 수 있을 것이라 생각되어 공유 해봅니다. 틀린 부분을 알려주신다면 감사하겠습니다.

 

728x90
반응형