IT/JavsScript

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

라임웨일 2022. 7. 13. 10:21
반응형

 

📖 이벤트 루프란 무엇인가요?

콜스텍(Call Stack)에서 이벤트가 순차적으로 진행되면 이어서 콜백큐(Callback Queue)에서 하나씩 동작을 Loop 시키는 것을 말합니다.  자바스크립트는 싱글 스레드 기반의 언어이고, 자바스크립트 엔진은 하나의 호출 스택만을 사용합니다. 이는 요청이 동기적으로 처리되어, 한 번에 한 가지 일만 처리할 수 있음을 의미합니다.

그러나 자바스크립트가 사용되는 환경을 생각해보면 우리는 많은 작업이 동시에 처리되고 있음을 알 수 있습니다. 예를 들면 브라우저에서 특정 이벤트를 발생시키고 동시에 여러 데이터를 호출해오는 경우가 발생하죠. 이런 환경이 가능하게 하는 것은 네트워크 요청과 같은 동작이 비동기적으로 이루어지기 때문입니다. 

 

💡 이벤트 루프가 왜 필요할까?

 자바스크립트는 싱글 스레드 기반의 언어지만, 자바스크립트가 구동되는 환경(Node.js, 브라우저)은 여러 스레드가 사용되는데 여러 스레드가 사용되는 구동 환경이 자바스크립트 엔진과 연동하기 위해 사용되는 장치가 '이벤트 루프' 입니다. 웹 사이트나 애플리케이션의 코드는 메인 스레드에서 실행되며, 같은 이벤트 루프를 공유합니다.

 

👉 메인 스레드의 역할

메인 스레드는 사이트의 (1)코드를 실행시킬 뿐만 아니라, (2)이벤트들을 받고 실행시키거나, (3)웹 컨텐츠를 렌더링 하거나 페인팅하는 일들을 하게 됩니다. 즉, 이벤트 루프는 스레드 안에 있는 코드들을 스케쥴링하고 실행시키는 역할을 담당합니다.

 

👉 이벤트 루프의 종류

이벤트 루프는 세 가지 종류가 있다.

  • window event loop
    - 같은 origin인 모든 윈도우는 윈도우 이벤트 루프를 공유한다.
    - 모든 윈도우들은 동기적으로 소통할 수 있게 된다.
  • worker event loop
    - window event loop와는 독립적으로 실행된다.
  • worklet event loop

 

💻 비동기 처리를 위한 브라우저

👉 브라우저 환경의 구조

  • 자바스크립트 엔진
    Heap : 객체들은 힙 메모리에 할당됩니다. 크기가 동적으로 변하는 값들의 참조 값을 갖고 있습니다.
    Call Stack : 함수 호출 시, 실행 컨텍스트가 생성되며, 이러한 실행 컨텍스트들이 콜 스택을 구성합니다.
  • Web API or Browser API
    - 웹 브라우저에 구현된 API
    - DOM event, AJAX, Timer 등이 있습니다.
  • 이벤트 루프
    - 콜 스택이 비었다면, 태스크 큐에 있는 콜백 함수를 처리합니다.
  • 태스크 큐
    - 이벤트 루프는 하나 이상의 태스크 큐를 갖습니다.
    - 태스크 큐는 태스크의 Set입니다.
    - 이벤트 루프가 큐의 첫 번째 태스크를 가져오는 것이 아니라, 태스크 큐에서 실행 가능한(runnable) 첫 번째 태스크를 가져오는 것으로 태스크 중에서 가장 오래된 태스크를 가져옵니다.

 

💻 마이크로 태스크와 매크로 태스크 (microtask, macrotask)

 

👉  마이크로 태스크 vs 매크로 태스크

두 비동기 작업들을 처리하는 방법들로 비동기 작업들은 테스크 큐라는 저장공간에 들어가게 됩니다. 태스크 큐는 발생한 순서대로 큐에 쌓이고 이벤트 루프에 의해 처리되며 태스크큐는 매크로 태스크 큐 와 마이크로 태스크로 구분할 수 있는데, 이 둘의 차이는 처리할 작업의 우선순위 입니다. 마이크로 태스크는 매크로 태스크 보다 우선순위가 높습니다.

 

그렇기 때문에 항상 마이크로태스크의 작업이 더 먼저 처리됩니다. 

 

✔ 매크로와 마이크로에 속하는 작업들

  • 매크로 태스크(macrotasks) - DOM 이벤트 콜백, 타이머(setTimeout, setInterval), 스크립트 로딩, requestAnimationFrame
  • 마이크로태스크(microtasks) - 프로미스(Promises) 핸들러 (then / catch / finally) + await,  Object.observe, process (MutationObserver 등)   

 

- 결과 예측해보기

console.log('콜 스택!');
setTimeout(() => console.log('태스크 큐!'), 0);
Promise.resolve().then(() => console.log('마이크로태스크 큐!'));

- 실행 결과

콜 스택!			
마이크로태스크 큐!	
태스크 큐!

 

💻 이벤트 루프의 동작 방식

👉 이벤트 루프는 다음을 반복합니다.

  1. 호출스택이 비었는지 지속적으로 확인합니다.
  2. 호출 스택이 비게 되면 제일 먼저 마이크로 태스크 큐를 확인하고 가장 오래된 태스크부터 꺼내서 호출스택으로 전달해 주는데, 이걸 마이크로태스크 큐가 텅 비어있을때까지 수행합니다.
  3. 모든 마이크로태스크가 처리된 직후, 렌더링 작업이 필요하면 렌더링을 수행합니다. 
  4. 매크로 태스크 큐를 확인합니다.
  5. 매크로 태스크 큐에서 가장 오래된 태스크 하나를 꺼내 호출 스택에 전달해 줍니다.
  6. 다시 1번 으로 돌아갑니다.

 

👉 위 절차를 아래 예시를 통해 더 자세히 살펴봅시다

 

✔ 처리되길 기다리는 태스크들

  1. 현재 호출스택에 작업들이 많아서 자바스크립트 엔진이 바쁜 와중에 여러 비동기 작업들이 큐에 쌓여있는 상황입니다.
  2. 이벤트 루프는 태스크들을 처리하기 위해 호출 스택이 비었는지 계속 확인하며 호출 스택이 비었다면, 이벤트 루프는 가장 먼저 마이크로 태스크 큐에 쌓여있는 태스크들을  Promise then -> Promise then -> Observer callback 순서로 모두 처리할 것입니다. 그리고 매크로 태스크 큐를 처리하기 전에 UI 렌더링 작업이 필요하면 렌더링을 이때 수행합니다.
  3. 이제 매크로태스크 큐의 click callback을 처리하고 다시 마이크로 태스크 큐를 확인합니다. 만약 마이크로 태스크 큐에 처리할 태스크들이 또 쌓여있다면 그것들을 모두 처리한 후 다시 렌더링 작업을 수행하고 매크로 태스크의 setTimeout callback을 처리합니다.

위 예시의 작업 순서 중 필수로 알아야 할 개념

여기서 주목할 부분은, 브라우저는 매크로태스크 하나를 처리할 때마다 마이크로 태스크 전부를 다 처리하고 렌더링을 수행한는 것입니다. 그래서 마이크로태스크가 모두 처리되기 전까지는 UI 렌더링이나 네트워크 요청은 절대 일어나지 않습니다.

 

✔ 코드 예시 

이제 코드를 통해 정말 위의 순서대로 실행되는지 확인해 봅시다. 그리고 어떻게 실행될 지 코드를 예측해 봅시다.

<script>
    console.log('시작');

    setTimeout(()=> console.log('타이머')); // (A)

    Promise.resolve()
    .then(()=> console.log('프로미스 1')) // (B)
    .then(()=> console.log('프로미스 2')); // (C)

    console.log('끝'); // (D)
</script>

 

✔  코드 실행 결과

코드 실행 결과 => console.log

  1. console.log 는 일반적인 동기 코드이므로 바로 호출 스택에서 실행되므로 '시작' 이 가장 먼저 출력됩니다. (참고로 console.log 도 Web API 인데, Web API라고 해서 모두 태스크 큐로 가는 것은 아니고 비동기적으로 실행되는 Web API 들만 큐로 이동)
  2. (A) 에서 setTimeout을 만나면 자바스크립트 엔진은 호출 스택에서 setTimeout을 바로 실행하지 않고 Web API로 보냅니다. Web API는 setTimeout의 지연시간만큼 지난 후 (예제에선 0ms 이므로 0ms 만큼 대기)  매크로 태스크 큐에 콜백을 넣어줍니다.
  3. 그다음에 (B)에서 이행된 상태의 Promise then을 만나게 되고, 이 then은 마이크로 태스크 큐에 들어가게 됩니다.
  4. 마지막으로 (D) 에서 console.log를 만나 '끝'을 출력합니다.

 

출처 :

반응형
광고차단(애드블록)프로그램이나 브라우저를 사용중이시면 프로그램을 비활성화이나 블로그 주소를 예외 처리 해주시면 광고가 노출됩니다. 귀찮고 번거롭겠지만 광고 클릭은 저에게는 큰 힘이 됩니다. 🙇🏻‍♂️🙇🏻‍♀️
제 블로그의 모든 글은 제가 직접 작성 하고 다른 글을 참고할 때는 이전 글보다 읽기 편하게 수정해서 작성하고 있습니다. 커피 한잔 사먹고 더 열심히 좋은글로 보답하겠습니다.
오늘도 제 블로그에 와 주셔서 감사합니다. :)
//