JavaScript의 queueMicrotask()와 함께 마이크로태스크 사용하기 - Web API | MDN

마이크로태스크는 자신을 생성한 함수 또는 프로그램이 종료됐고 JavaScript 실행스택이 빈 후에 사용자 에이전트(브라우저)가 스크립트 실행 환경을 운용하기 위해 사용하는 이벤트 루프로 통제권을 넘기기 전에 실행되는 짧은 함수이다.

이때의 이벤트 루프는 브라우저의 주 이벤트 루프 또는 웹 어커를 구동하는 이벤트 루프이다. 따라서 마이크로태스크를 이용하면 다른 스크립트의 실행을 방해할 위험을 감수하지 않으면서도, 사용자 에이전트(브라우저)가 반응하기 전에 주어진 함수를 실행할 수 있다.

JavaScript PromiseMutation Observer API 둘 다 마이크로태스크 큐를 사용해 콜백을 호출하지만, 때로는 현재 이벤트 루프가 정리될 때까지 작업을 미루는 기능이 직접 필요할 때가 있다. 그래서 서드파티 라이브러리, 프레임워크, 폴리필에서 마이크로태스크를 사용할 수 있도록, Window와 Worker 인터페이스는 queueMicrotaks() 메서드를 노출하고 있다.

태스크 vs 마이크로태스크

마이크로태스크를 올바르고 이야기하기 위해선, 우선 JavaScript에서의 태스크란 무엇인지, 그리고 마이크로태스크가 태스크와 어떻게 다른지 아는 것이 필요하다. 자세히 알아보려면 **In depth: Microtasks and the JavaScript runtime environment 를 확인.**

태스크

task는 프로그램 처음 실행되거나 이벤트 콜백이 실행되거나 인터벌 또는 타임아웃이 발생하는 것과 같은 표준 메커니즘을 통해 실행되기로 예약된 모든 JavaScript 코드이다. 이러한 모든 작업은 task queue에 예약된다.

태스크는 다음과 같은 경우에 태스크 큐에 추가된다.

  1. 새로운 JavaScript 프로그램이나 서브프로그램이 직접 실행될 때(콘솔에서 실행하거나 <script> 요소의 코드를 실행하는 등).
  2. 이벤트가 발생하면 해당 이벤트의 콜백 함수가 태스크 큐에 추가된다.
  3. setTimout()이나 setInterval()을 사용하여 생성한 타임아웃이나 인터벌이 만료되면 해당 콜백이 태스크 큐에 추가된다.

코드를 구동하는 이벤트 루프는 태스크를 한 번에 하나씩 처리하며, 태스크 큐에 추가된 순서대로 처리한다. 가장 오래된 실행 가능한 태스크가 이벤트 루프의 단일 반복 동안 실행된다. 이후에는 마이크로태스크가 마이크로태스크 큐가 비워질 때까지 실행되고, 그 다음 브라우저는 렌더링을 업데이트하기로 결정할 수 있다. 그런 다음 브라우저는 이벤트 루프의 다음 반복으로 넘어간다.

Microtasks

처음에는 마이크로태스크와 태스크의 차이가 사소해 보일 수 있다. 둘 다 JavaScript 코드로 구성되어 있으며, 적절한 시간에 큐에 배치되고 실행된다. 그러나 이벤트 루프는 이터레이션을 시작할 때 큐에 있는 태스크만을 하나씩 순서대로 실행하는 반면, 마이크로태스크 큐는 다르게 처리한다.

이 두 가지 주요한 차이점이 있다.

첫째, 각각의 태스크가 종료될 때마다 이벤트 루프는 해당 태스크가 다른 JavaScript 코드에 제어를 반환하는지 확인한다. 그렇지 않은 경우, 이벤트 루프는 마이크태스크 큐에 있는 모든 마이크로태스크를 실행한다. 마이크로태스크 큐는 이벤트 및 다른 콜백 처리 후에도 이벤트 루프의 반복마다 여러 번 처리된다.

둘째, 만약 마이크로태스크가 queueMicrotask()를 호출하여 큐에 더 많은 마이크로태스크를 추가한다면, 추가된 마이크로태스크들은 다음 태스크가 실행되기 전에 실행된다. 이는 이벤트 루프가 큐에 남은 마이크로태스크가 없을 때까지 계속해서 마이크로태스크를 호출하기 때문이다.

<aside> ⚠️ Warning: 마이크로태스크가 자체적으로 더 많은 마이크로테스크를 큐에 추가할 수 있으며, 이벤트 루프는 큐가 비워질 때까지 계속해서 마이크로태스크를 처리하기 때문에, 이벤트 루프가 마이크로태스크를 끝없이 처리하는 위험이 있다. 마이크로태스크를 재귀적으로 추가하는 방법에 주의해야 한다.

</aside>