노트

마이크로태스크

Microtask

프런트엔드#js · 연결된 개념 6개

쉽게 말하면

마이크로태스크는 바리스타가 지금 잔을 다 만들고 다음 주문을 받기 전에, '아 이것도요' 하고 붙은 짧은 일을 전부 먼저 끝내는 것과 같아요. Promise의 then 콜백이 이렇게 지금 코드 바로 뒤에 돌아요.

비유가 깨지는 곳 '이것도요'가 끝없이 이어지면 다음 손님은 영영 못 와요. 마이크로태스크가 자기 자신을 계속 등록하면 렌더링도 끼어들지 못해 화면이 멈추고, setTimeout이면 사이사이 화면이 그려져요.

현재 실행 중인 코드가 끝난 직후, 다음 태스크로 넘어가기 전에 몰아서 처리되는 작은 작업. 이벤트 루프는 태스크 하나를 끝낼 때마다 마이크로태스크 큐가 빌 때까지 전부 실행한다.

  • 들어가는 것: Promise의 then·catch·finally 콜백, await 다음에 이어지는 코드, queueMicrotask(), MutationObserver 콜백
  • 같은 태스크 안에서 setTimeout을 먼저 등록했어도 마이크로태스크가 항상 먼저 실행된다
  • 처리 중에 새로 추가된 마이크로태스크도 같은 차례에 처리한다. 그래서 마이크로태스크가 자기 자신을 계속 등록하면 루프를 빠져나가지 못하고 화면이 멈춘다. 같은 재귀라도 setTimeout으로 등록하면 사이사이 렌더링이 끼어들어서 화면은 살아 있다
function loopTimeout() { setTimeout(loopTimeout) }          // 느리지만 화면은 그려짐
function loopMicro()   { queueMicrotask(loopMicro) }         // 탭이 멈춤

then 체인의 순서

체인의 다음 then은 앞 콜백이 끝나야 큐에 들어간다. 그래서 두 체인을 나란히 만들면 단계별로 번갈아 실행된다.

Promise.resolve().then(() => log('1-1')).then(() => log('1-2'))
Promise.resolve().then(() => log('2-1')).then(() => log('2-2'))
// 1-1, 2-1, 1-2, 2-2

React가 일부 상태 업데이트를 모아 처리하거나(자동 배칭) 상태 관리 라이브러리가 알림을 미루는 데에도 이 "현재 코드 직후" 타이밍이 쓰인다.

참고: MDN — Using microtasks in JavaScript with queueMicrotask()

연결된 개념

이 노트를 가리키는 문서

뜻이 가까운 노트

  • 스택

    나중에 넣은 것을 먼저 꺼내는(Last In, First Out) 자료구조. 접시를 쌓듯 맨 위에서만 넣고(push) 꺼낸다(pop). 넣기·꺼내기 모두 O(1)이다.

  • 동기·비동기와 블로킹·논블로킹

    동기·비동기는 결과를 언제 어떻게 받느냐, 블로킹·논블로킹은 기다리는 동안 호출한 스레드가 멈추느냐의 문제다.

  • 우선순위 큐

    원소마다 우선순위가 있고, 들어온 순서와 상관없이 우선순위가 가장 높은 것부터 꺼내는 추상 자료형(Abstract Data Type, ADT). 같은 우선순위끼리의 순서는 보장하지 않는다. 응급실 대기 순서가 좋은 비유다.

  • use()로 Promise 읽기

    use()는 렌더 중에 Promise나 Context 같은 리소스의 값을 읽는 React 19 API(Application Programming Interface)다. Promise가 아직 pending이면 컴포넌트가 suspend되어 가장 가까운 suspense의 fallback이 보이고, 끝나면 그 값으로 다시 렌더된다. reject되면 가장 가까운 에러 경계(Error Boundary)로 던져진다.

  • 마이크로 프론트엔드

    마이크로 프론트엔드는 하나의 큰 프론트엔드 앱을 기능별 조각으로 나눠, 팀마다 따로 개발·배포하고 런타임에 하나의 화면으로 조립하는 아키텍처다. 백엔드의 마이크로서비스(microservices) 발상을 프론트엔드로 가져온 것이다.

보기 옵션