Skip to content

자바스크립트 비동기 처리 (2/2)

Share on facebook
Facebook
Share on twitter
Twitter
Share on linkedin
LinkedIn

들어가기 전에

이전 글 ‘자바스크립트 비동기 처리 (1/2)‘에서 자바스크립트 엔진과 비동기 처리를 위한 런타임 환경에 대해서 알아보았다.

이번 글에서는 자바스크립트에서 비동기 처리를 가능하게 해주는 태스크 큐 (task queue)와 이벤트 루프 (event loop)에 대해 알아보겠다.

태스크 큐 (Task queue)

태스크 큐는 사용하는 API에 따라서 (매크로) 태스크 큐(macrotask queue)와 마이크로태스크 큐(microtask queue)로 구분된다.

(매크로) 태스크 큐 (Macrotask queue)

  • 사용하는 API : setTimeout, setInterval, setImmediate, requestAnimationFrame, I/O, UI rendering

마이크로태스크 큐 (Microtask queue)

: 태스크 큐보다 높은 우선순위를 갖고 먼저 처리된다.

  • 사용하는 API : process.nextTick, Promise, queueMicrotask(f), MutationObserver

이벤트 루프 (Event loop)

이벤트 루프는 지속적으로 콜 스택(call stack)과 태스트 큐(콜백 큐, callback queue)를 모니터링하여 콜 스택이 비어있다면 태스트 큐에 있는 콜백 함수를 콜 스택으로 옮겨 처리한다.

또한, 이벤트 루프는 마이크로태스트 큐에 있는 모든 태스크를 처리한 다음, 매크로태스크에 있는 큐를 처리한다.

이벤트 루프 동작 방식

1. 콜 스택이 비어있으면 마이크로태스크 큐에 적재된 작업이 있는지 확인

2. 마이크로태스크 큐에 적재된 작업을 콜 스택으로 순차적으로 옮겨 실행하고 비어있으면 매크로태스크 큐에 적재된 작업이 있는지 확인

3. 매크로태스크 큐에 적재된 작업을 콜 스택으로 옮겨 실행

4. 위의 과정을 반복

다음 코드를 통해 (매크로) 태스크 큐와 마이크로태스크 큐에 적재된 작업이 어떻게 처리되는지 확인해보자.

console.log('[1]');
setTimeout(function () {console.log("[2]")}, 0);

const p = Promise.resolve();
p.then(function() {
    setTimeout(function() {
        console.log('[3]')
        setTimeout(function() {console.log("[4]")}, 0);
        p.then(() => console.log('[5]'));
    }, 0);
    console.log("[6]");
});

console.log("[7]")

1. 이벤트 루프가 로드된 스크립트를 실행시키면 처음 console.log('[1]')를 콜 스택으로 옮기고 코드가 실행된다.

2. console.log('[1]') 함수가 종료되면 콜 스택에서 제거되고 setTimeout()이 콜 스택으로 이동해 Web API에서 타이머를 수행한 후 태스크 큐에 적재된다.

3. Promise.resolve() 함수가 콜 스택으로 적재되고 콜백 함수인 then이 마이크로태스크 큐에 적재된다.

4. console.log('[7]')이 콜 스택에 적재되고 코드가 실행된다.

5. 이벤트 루프는 우선순위가 높은 마이크로태스크 큐에 있는 then을 콜 스택으로 적재해 then 안에 있는 setTimeout을 처리해 태스크 큐에 적재하고 console.log는 콜 스택으로 적재한다.

6. 태스크 큐에 있는 첫번째 timer를 콜 스택에 적재하고 console.log('[2]') 가 수행된다.

7. console.log('[2]') 수행 후 콜 스택이 전부 비워지면 이벤트 루프는 태스크 큐에 있는 timer를 콜 스택에 적재해서 console.log('[3]'), setTimeout, then이 실행된다.

8. console.log('[3]')이 출력되고 콜 스택이 전부 비워지면 이벤트 루프는 우선순위가 높은 마이크로태스크 큐에 있는 then을 콜 스택에 적재하고 console.log('[5]')이 실행된다.

9. console.log('[5]'이 출력되고 콜 스택이 전부 비워지면 태스크 큐에 있는 timer를 콜 스택에 적재해 console.log('[4]')이 실행된다.

결론

자바스크립트 구현 시 매크로태스크, 마이크로태스크에 따라서 처리되는 우선순위가 다르기 때문에 둘의 작동방식을 이해하고 사용하는 것은 중요하다. 또한, 이벤트 루프는 자바스크립트 런타임 환경이기 때문에 사용하는 런타임에 따라서 상세 구현이 다르다. (Node.js에서 비동기 처리를 담당하는 libuv 라이브러리는 HTML 스펙을 따르지 않기 때문에 상세 구현이 다르다.) 본 글에서는 HTML 스펙에 대한 내용만 다루었기 때문에 나중에 기회가 된다면 Node.js의 libuv에 대해서도 정리해 볼 계획이다.

Share your blockchain-related digital insights with your friends

Share on facebook
Facebook
Share on twitter
Twitter
Share on linkedin
LinkedIn

Get more insights