[JavaScript] 이벤트 루프 (구조, 동작, 매크로태스크, 마이크로태스크, Web APIs)

mori·2024년 8월 7일
post-thumbnail

프엔 공부 중 빠지지 않는 이벤트 루프!
비동기 처리를 가능하게 해주는 이벤트 루프 제대로 이해해보자고! 😀😀😀


이벤트 루프

🟨 1. 자바스크립트와 이벤트 루프

자바스크립트는 싱글 스레드 언어로 한 번에 하나의 코드만 처리할 수 있다.
만약 싱글 스레드로 모든 브라우저 동작이 실행된다면, 우리는 파일 다운로드 중에는 다른 작업을 아무것도 못하고 대기해야 하는 상황이 생긴다. 그렇기 때문에 우리는 파일 다운로드, 이벤트, 네트워크 요청과 같이 비동기처리 방식이 필요할 때가 아주 많이 있다.
이렇게 파일 다운, 타이머, 네트워크 요청과 같이 오래 걸리는 작업들은 동시에 작업 처리를 진행하도록 해야하는 데 이러한 비동기 작업을 효율적으로 관리하는 것이 바로 이벤트 루프이다!
💁‍♀️ 자바스크립트에서 여러 작업을 동시에 처리하거나, 여러 작업 중 우선적으로 실행할 작업을 결정하는 관리자 역할을 하는 것이 "이벤트 루프" 이다.



🟨 2. 이벤트 루프

자바스크립트는 위 이미지의 구조로 되어있고 Event Loop는 브라우저 내부의 Call Stack, Web APIs, Callback Queue 등의 요소들을 모니터링하며 비동기적으로 실행되는 작업을 관리하고, 이를 순서대로 처리하며 프로그램 실행 흐름을 제어한다.

  • Heap : 선언한 변수, 함수와 같이 메모리가 할당 되는 저장 공간
  • Call Stack : 코드 실행을 위해 사용하는 메모리 공간 (코드가 쌓이는 공간)
  • Web APIs : 자바스크립트 엔진이 아닌 브라우저에서 제공하는 API 모음으로, 비동기적으로 실행되는 작업(setTimeout, Promise 등)들을 전담하여 처리
  • Callback Queue : 콜 스택에 있는 비동기적 작업이 완료되면 실행되는 함수들이 대기하는 공간

🔸 2-1. Callback Queue 종류

Callback Queue에는 macrotask queue(매크로 태스크 큐), microtask queue(마이크로 태스크 큐) 가 있다.

  • macrotask queue : setTimeout, setInterval, fetch, addEventListener 와 같이 비동기로 처리되는 함수들의 콜백 함수가 들어가는 큐 
  • microtask queue : 우선 시작! promise.then, process.nextTick, MutationObserver 와 같이 우선적으로 비동기로 처리되는 함수들의 콜백 함수가 들어가는 큐

💁‍♀️ Animation Frames?

  • animation frames (queue) : 브라우저 큐는 콜백 큐 이외에도 애니메이션 작업 처리를 담당하는 AnimationFrame Queue가 있다.자바스크립트 애니메이션 동작을 제어하는 requestAnimationFrame 메소드를 통해 콜백을 등록하면, 해당 큐에 적재되어 Repaint 작업 직전에 AnimaitionFrame Queue에 있는 작업들을 모두 처리한다.

⭐전체적인 이해를 위해 반드시 알아야하는 실행 순서!⭐
실행 순서 : Microtask Queue > Animation Frame > Task Queue



🟨 3. 이벤트 루프 동작 과정

이벤트 루프는 비동기 작업을 Web API에 옮기고 작업이 완료되면 Queue에 적재했다가 Call Stack에 작업을 관리, 옮기는 역할을 한다.
Call Stack, Task Queue에 작업이 남아있는지 반복적으로 무한 루프하며 확인하기 때문에 이벤트 "루프"이다.

🔸 3-1. setTimeOut 동작 과정

function bar() {
  setTimeout(() => {
  	console.log("Second")
  }, 500);
}

function foo() {
  console.log("First");
}

function baz() {
  console.log("Third");
}

bar();
foo();
baz();

//노출 순서
First
Second
Third

위 스크립트는 아래 코드 실행 과정으로 진행된다.

  1. bar() 함수 호출 -> setTimeout() -> stack -> 콜백 함수 -> web api이동 타이머 진행
  2. foo() 함수 호출 -> stack -> 콘솔 출력 First
  3. 5초 완료 시 web api 콜백 함수 -> task queue 이동
  4. baz() 함수 호출 -> stack -> 콘솔 출력 Second
  5. 이벤트 루프가 비어진 Call Stack 확인 후 task queue에 있던 콜백 함수를 Call Stack으로 이동
  6. 콘솔 출력 Third

🔸 3-2. Promise 동작 과정

💁‍♀️ 코드와 gif를 비교하며 보면 이해가 훨씬 쉽다 ㅎ.ㅎ

console.log('Start!');

setTimeout(() => {
	console.log('Timeout!');
}, 0);

Promise.resolve('Promise!').then(res => console.log(res));

console.log('End!');

//노출 순서
Start!
End!
Promise!
Timeout!
  1. 콘솔 코드 stack 적재 -> 콘솔 출력 Start!
  2. setTimeout -> stack -> 콜백 함수 -> web api이동 타이머 진행 (0초라 바로 타이머 종료)
  3. 이벤트 루프에 의해 setTimeout 콜백 함수는 MacroTask Queue 적재
  4. Promise 코드 -> stack -> 이벤트 루프에 의해 then 핸들러의 콜백 함수 MicroTask Queue 적재
  5. 콘솔 코드 stack 적재 -> 콘솔 출력 End!
  6. Call Stack에 동기 작업 없음 => 비워짐!
  7. 이벤트 핸들러에 의해 queue에 있는 작업들을 stack으로 이동
  8. 항상 MicroTask Queue 작업 먼저 우선 처리 -> 콘솔 출력 Promise!
  9. MacroTask Queue -> 콘솔 출력 Timeout!

🔸 3-3. Animation Frames 동작 과정

Animation Frames는 브라우저가 화면을 다시 그릴 때 실행되는 함수들을 담아두는 공간이다.

👇requestAnimationFrame 메소드 예시

Animation Frames의 실행 순서와 우선순위는 브라우저에 따라 다를 수 있으며, 이벤트 루프의 명세가 명확하게 정의되지 않은 부분이 있기 때문에 브라우저마다 동작이 다를 수 있다.
위 설명과 같이 Microtask Queue > Animation Frame > Task Queue 순서가 일반적이지만, 항상 보장되는 것은 아니다.
특정 브라우저의 동작 방식이나 업데이트된 이벤트 루프에 따라 다를 수 있기에, 정확한 확인을 위해서는 크로스 브라우저 테스트가 필요하다.

실제 브라우저 동작 예

  • Chrome, Firefox: Microtask Queue가 비어있을 때, requestAnimationFrame 콜백이 실행된 후에 Task Queue가 처리
  • Safari: 일부 경우 requestAnimationFrame 콜백이 Task Queue보다 먼저 실행될 수 있지만, 명확히 정의되지 않은 경우도 있다.

💁‍♀️ Animation Frames 동작 과정

  1. 콘솔 출력 script start
  2. setTimeout -> stack -> 콜백 함수 -> web api이동 타이머 진행 (0초라 바로 타이머 종료)
  3. Promise 코드 -> stack -> 이벤트 루프에 의해 then 핸들러의 콜백 함수 “promise1” MicroTask Queue 적재
  4. requestAnimationFrame 함수 -> stack -> 이벤트 루프에 의해 콜백 함수 AnimationFrame 적재
  5. 콘솔 출력 script end
  6. 콘솔 출력 promise1
  7. Promise 코드 -> stack -> 이벤트 루프에 의해 then 핸들러의 콜백 함수 “promise2” MicroTask Queue 적재
  8. 콘솔 출력 promise2
  9. 콘솔 출력 animation
  10. 콘솔 출력 setTimeout

🟨 4. 이벤트 루프 추천 사이트

👩‍💻프엔이라면 반드시 알아야 할 이벤트 루프!
직접 코드를 써보고 조작해볼 수 있는 사이트와 함께 순서를 확인해보자

🔎직접 이벤트 루프 사용해보기


처음 이벤트 루프를 접했을 때는 동공지진이 왔었지만, 계속 반복해서 다양한 자료들을 찾아보니 점점 이해가 되었다! 역시 복습이 체고 🫶





✅ 참고
https://inpa.tistory.com/entry/%F0%9F%94%84-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EB%A3%A8%ED%94%84-%EA%B5%AC%EC%A1%B0-%EB%8F%99%EC%9E%91-%EC%9B%90%EB%A6%AC
https://hudi.blog/async-javascript/
_https://meetup.nhncloud.com/posts/89

https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/

profile
지식을 나눠요 📓

0개의 댓글