소개
queueMicrotask는 동기 코드를 비동기 방식으로 변환할 수 있게 해주는 새로운 브라우저 API입니다.
queueMicrotask(() => {
console.log('안녕하세요, 저는 queueMicrotask에 의해 비동기적으로 실행됩니다');
});이는 기존에 우리가 setTimeout으로 수행하던 작업과 유사합니다.
setTimeout(() => {
console.log('안녕하세요, 저는 setTimeout에 의해 비동기적으로 실행됩니다');
}, 0);그렇다면 이미 setTimeout이 있는데, 굳이 queueMicrotask를 사용해야 하는 이유는 무엇일까요?
queueMicrotask는 함수(태스크)를 큐에 추가하며, 현재 태스크가 작업을 완료한 후 실행 컨텍스트의 제어권이 브라우저의 이벤트 루프로 반환되기 전에, 대기 중인 다른 코드가 없을 때 각 함수가 순서대로(FIFO) 실행됩니다.
즉, queueMicrotask의 태스크는 현재 콜 스택이 비워진 직후, 실행 흐름이 이벤트 루프로 넘어가기 전에 실행됩니다.
반면 setTimeout의 경우, 제어권이 이벤트 루프로 넘어간 후에 각 태스크가 이벤트 큐에서 실행됩니다.
그렇다면 setTimeout을 먼저 실행하고 그다음 queueMicrotask를 실행하면, 어떤 것이 먼저 호출될까요? 아래 코드를 직접 실행해서 확인해 보세요.
setTimeout(() => {
console.log('안녕하세요, 저는 setTimeout에 의해 비동기적으로 실행됩니다');
},0);
queueMicrotask(() => {
console.log('안녕하세요, 저는 queueMicrotask에 의해 비동기적으로 실행됩니다');
}); 참고로 Node.js 환경에서는 "process.nextTick"이 동일한 역할을 수행합니다.
언제 사용해야 할까?
queueMicrotask를 반드시 사용해야 하는 엄격한 규칙은 없지만, 현재 실행 중인 작업을 멈추지 않으면서 특정 코드를 실행해야 할 때 유용하게 활용할 수 있습니다.
예를 들어, 값들의 목록을 관리하는 배열이 있다고 가정해 보겠습니다. 값이 삽입될 때마다 배열을 정렬하면 이후 검색 속도가 훨씬 빨라집니다.
var arr=[];
function add(value){
arr.push(value);
arr.sort();
}하지만 문제는 요소 검색이 사용자가 검색 입력창을 사용할 때마다 발생한다는 점입니다. 이벤트 핸들러는 제어권이 이벤트 루프로 넘어간 후에 호출되기 때문에, 데이터 정렬 작업이 다른 중요한 동기 코드의 실행을 막게 될 수 있습니다.
다음은 queueMicrotask를 활용해 이 코드를 개선한 예시입니다:
var arr = [];
function add(value) {
arr.push(value);
queueMicrotask(() => {
arr.sort();
})
}이렇게 하면 배열 정렬 작업이 마이크로태스크 큐로 밀려나, 현재 실행 중인 동기 코드가 모두 완료된 직후에 실행됩니다. 결과적으로 데이터 추가 작업의 응답성이 향상되고, 정렬은 여전히 검색이 시작되기 전에 완료됩니다.