이벤트 루프와 태스크 큐(마이크로, 매크로 태스크 큐)

hatban·2023년 4월 16일
0

자바스크립트는 싱글 스레드 기반의 언어인데, 즉 하나의 호출 스택만을 사용한다. 하지만 비동기적으로 일을 처리할 수 있다!

비동기 처리를 위한 브라우저의 구조

브라우저 환경의 구조

자바스크립트 엔진 구성

  • Heap : 객체들은 힙 메모리에 할당된다. 크기가 동적으로 변하는 값들의 참조 값을 갖고있다
  • Call Stack : 함수 호출 시 함수 컨텍스트가 생성되고, 이 컨텍스트들이 콜스택에 쌓인다

Web API or Browser API

  • 웹 브라우저에 구현된 API다
  • DOM event, AJAX, Timer 등이 있다.

이벤트 루프

  • 콜 스택이 비어있다면 태스크 큐에 있는 콜백함수를 처리한다

태스크 큐

  • 이벤트 루프는 하나 이상의 태스크 큐를 갖고 있다
  • 콜백 큐는 태스크 큐의 한 종류일 수 있다
  • 태스크 큐는 태스크의 Set이다
  • 이벤트 루프가 큐의 첫 번째 태스크를 가져오는게 아닌, 태스크 큐에서 실행가능한 첫 번째 태스크를 가져온다. 태스크 중에서 가장 오래된 태스크를 가져온다.

이벤트 루프

자바스크립트는 싱글 스레드 기반의 언어지만, 자바스크립트가 구동되는 환경(브라우저, Node.js)은 여러 스레드가 사용된다.
여러 스레드가 사용되는 구동 환경이 자바스크립트 엔진과 연동하기 위해 사용되는 장치가 '이벤트 루프'이다.


마이크로 태스크와 매크로 태스크

마이크로 태스크

  • 마이크로 태스크들은 실행하면서 새로운 마이크로 태스크를 큐에 추가할 수도 있다. 새롭게 추가된 마이크로 태스크도 큐가 빌 때까지 계속해서 실행된다.

매크로 태스크

  • 이벤트 루프는 매크로 태스크 큐에 있는 것을 실행시키기 시작할 때, 있는 매크로 태스크만 실행시킨다.
  • 매크로 태스크가 추가한 매크로 태스크는 다음 이벤트 루프가 실행될 때까지 실행되지 않는다.

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


이벤트 루프의 동작 방식

  1. 매크로 태스크 큐에서 가장 오래된 태스크를 꺼내 실행시킨다
  2. 마이크로 태스크 큐에 있는 모든 태스크를 실행시킨다
  3. 렌더링 작업을 실행한다
  4. 매크로 태스크 큐에 새로운 매크로 태스크가 나타날 때까지 대기한다
  5. 1번으로 돌아간다

예시

console.log('script start'); // A

setTimeout(function () { // B
  console.log('setTimeout');
}, 0);

Promise.resolve() 
  .then(function () { // C
    console.log('promise1');
  })
  .then(function () { // D
    console.log('promise2');
  });

console.log('script end'); // E
//결과
script start
script end
promise1
promise2
setTimeout
  1. 콜 스택에는 전역 실행 객체가 있고, '스크립트 실행'이라는 태스크가 매크로 태스크 큐에 들어있다.
  2. 이벤트 루프는 매크로 태스크 큐에 있는 '스크립트 실행' 태스크를 실행한다.
  3. A에 도달하면, 'script start'가 출력된다.
  4. B에 도달하면, setTimeout web api가 타이머를 실행시키고, 타이머가 종료되면 콜백 함수가 매크로 태스크 큐에 들어간다.
  5. C에 도달하면, 콜백 함수가 마이크로 태스크 큐에 들어간다.
  6. E에 도달하면, 'script end'가 출력된다.
  7. 콜 스택이 비었으므로, 이벤트 루프는 마이크로 태스크 큐에 있는 프라미스 콜백 함수를 실행시킨다.
  8. 'promise 1'이 출력된다.
  9. Promise.then 메서드는 D 콜백 함수를 마이크로 태스크 큐에 등록한다.
  10. 이벤트 루프는 다음 마이크로 태스크인 D 콜백 함수가 실행시킨다.
  11. 'promise 2'가 출력된다.
  12. 렌더링할 것이 있으면, 브라우저는 렌더링을 한다.
  13. 매크로 태스크 큐에 있는 setTimeout 콜백함수를 실행시킨다.
  14. 'setTimeout'이 출력된다.

후기

실행컨텍스트에 대해 공부하면서 간단하게 이벤트 큐가 있고 이벤트 큐가 콜백큐에 있는 콜백함수를 콜스택에 밀어넣어줘서 비동기적으로 처리된다고만 알고 있었는데, 콜백 큐는 그냥 태스크 큐의 하나고, 태스크 큐가 마이크로큐, 매크로 큐로 나눠진다는 것을 이번 기회를 통해 알게 되었다.

그리고 setTimeout이나 promise와 같이 함수 처리와 관련된 API 및 객체들이 어떻게, 왜 이때 동작하는지 조금이나마 이해할 수 있었다.

0개의 댓글