이벤트 루프(Event Loop) With 매크로 테스크, 마이크로 테스크

NSH·2022년 6월 14일
1
post-thumbnail

이벤트 루프란?

자바스크립트는 싱글 스레드 기반의 언어이며, 자바스크립트 엔진은 하나의 호출 스택을 사용한다. 이는 요청이 동기적으로 처리되고 한 번에 한 가지 일만 처리가 가능하다는 것을 말한다.

하지만 자바스크립트 구동 환경(브라우저, Node.js)은 여러 스레드를 사용하는데 여러 스레드를 사용하는 자바스크립트 구동 환경과 하나의 스레드를 사용하는 자바스크립트 엔진과 연동되기 위해서 이벤트 루프가 필요하다.

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

  • 자바스크립트 엔진
    • Heap: 객체들은 힙 메모리에 할당된다. 동적으로 변하는 값들의 참조이다.
    • Call Stack: 함수 호출 시 생성된 실행 컨텍스트들이 콜 스택을 구성한다.
  • Web API
    • 웹 브라우저에서 제공하는 API
    • Dom Event(document), Timer(setTimeout 등), AJAX
  • 태스크 큐
    • 하나 이상의 태스크를 가질 수 있다.
    • 첫 번째 태스크가 아닌 가장 오래되고 실행 가능한 태스크를 우선으로 실행한다.
  • 이벤트 루프
    • 콜 스택이 비어있을 때 태스크 큐에 있는 콜백 함수를 처리한다.

마이크로 태스크와 매크로 태스크

태스크 큐는 마이크로 태스크 큐와 매크로 태스크 큐로 구분된다. 이 두 태스크의 차이는 처리할 작업의 우선순위이며 마이크로 태스크가 매크로 태스크보다 우선순위가 높다.

마이크로, 매크로 태스크에 속하는 작업들이다.

  • 마이크로 태스크: 프로미스(Promise) 핸들러(then, catch, finally) + await, Mutation Observer, Object.observer
  • 매크로 태스크: Dom 이벤트 콜백, 타이머(setTimeout, setInterval), 스크립트 로딩, requestAnimationFrame

동작 예제

아래 예제를 통해서 동작 순서를 확인해보자.

// 코드 실행
console.log('콜 스택');
setTimeout(() => console.log('매크로 태스크'), 0);
Promise.resolve().then(() => console.log('마이크로 태스크'));

// 코드 실행 결과
콜 스택		
마이크로 태스크	
매크로 태스크

코드 실행 결과를 통해서 마이크로 태스크가 매크로 태스크보다 우선순위가 높은 것을 확인할 수 있다.

이벤트 루프 동작 방식

이벤트 루프는 아래의 과정을 반복한다.

  1. 호출 스택이 비었는지 확인한다.
  2. 호출 스택이 비었다면 마이크로 태스크 큐를 확인한다.
    a. 가장 오래되고 실행 가능한 태스크를 꺼내서 호출스택에 전달한다.
    b. 마이크로 태스크 큐가 다 비워질 때까지 수행한다.
  3. 마이크로 태스크 큐가 다 처리된 후 랜더링 작업이 필요하면 수행한다.
  4. 매크로 테스크 큐를 확인한다.
    a. 가장 오래되고 실행 가능한 태스크 하나를 꺼내서 호출 스택에 전달한다.
  5. 다시 1번으로 돌아간다.

동작 예제

이벤트 루프의 동작 방식을 이해한걸 바탕으로 아래 예제가 어떤 순서로 동작하는지 자세히 알아보자.

// 코드 실행
console.log('시작');

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

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

console.log('끝'); // (D)

// 코드 실행 결과
시작
끝
프로미스 1
프로미스 2
타이머
  1. console.log가 호출 스택에 쌓인다.
    a. ‘시작’ 출력
  2. (A)는 호출 스택에 쌓인 후 Web API로 보내고 시간이 지나면 매크로 태스크 큐로 보내진다.
  3. (B), (C)는 이행된 상태에 then을 만나고 마이크로 태스크 큐로 보내진다.
  4. console.log가 호출 스택에 쌓인다.
    a. ‘끝’ 출력
  5. 호출 스택이 비었으므로 이벤트 루프는 마이크로 태스크 큐에서 가장 오래되고 실행 가능한 태스크들을 순서대로 모두 처리한다.
    a. ‘프로미스 1’ 출력
    a. ‘프로미스 2’ 출력
  6. 마이크로 태스크 큐가 다 비었으니 매크로 태스크 큐에서 가장 오래되고 실행 가능한 태스크 하나를 처리한다.
    a. ‘타이머’ 출력
profile
잘 하고 싶다.

0개의 댓글