이벤트 루프

#javascript#web#runtime
• • •

1

  • 초기 컴퓨터 프로그램은 한 번에 하나의 작업만 처리
  • 입출력 기다리는 동안 CPU는 놀고 있음
  • 구조는 단순하지만 효율은 극악

2

  • 운영체제는 언제 올지 모르는 이벤트를 기다려야 함(키보드, 마우스 입력 등)
  • 계속 기다리지 않고 이벤트가 발생하면 처리하는 이벤트 기반 아키텍처 등장
  • GUI 시대의 등장으로 이벤트 루프는 필수가 됨
  • 이벤트 루프(Event Loop)는 블로킹 문제를 해결하기 위한 메커니즘이라고 할 수 있음
  • 이벤트 루프는 실행 가능한 작업이 생길 때까지 기다렸다가 하나를 선택해 실행하는 기본적인 프로그램 구조
  • 항상 그렇진 않지만 즉시 실행할 수 없는 작업을 큐로 관리하는 것이 일반적
  • 실행 가능한 순간마다 하나씩 처리하는 것이 일반적

3

  • 웹 서버의 시대가 되면서 동시 접속이 많아지면 싱글 스레드로는 역부족
  • 이를 해결하기 위한 멀티스레딩비동기 I/O + 이벤트 루프 등장
  • 이벤트 루프는 동시성(concurrency)를 해결하고 멀티스레드는 병렬성(parallelism)을 해결
  • 웹 서버 요청의 본질은 파일, DB 밑 네트워크의 기다림이기 때문에 비동기 I/O + 이벤트루프가 각광

4

  • Javascript는 싱글 스레드
  • 스레드 하나는 스레드 여러 개에 비해 안정적임
  • 특히 UI를 안정적으로 표현하는데 유리함
  • 멀티 스레드가 접근 가능한 DOM을 상상해보면 UI 안정성이 크게 낮아질 것
  • Web Worker 또한 같은 이유로 DOM에 접근 불가
  • 싱글 스레드와 이벤트 루프 조합은 예측 가능하고 디버깅이 상대적으로 쉬움
  • 게다가 JS가 들어오기 전부터 브라우저는 이미 이벤트 루프 구조였다고 함

5

  • Javascript로 실행한 코드는 콜 스택에 쌓이고 순차적으로 처리됨
  • setTimout, DOM 이벤트 콜백 등은 먼저 태스크 큐(Task Queue)에 쌓임
  • 이벤트 루프는 콜 스택이 비워질 때마다 큐에 있는 콜백을 하나씩 스택에 옮겨 실행
  • Promisethen과 같은 작업은 마이크로 태스크 큐(MicroTask Queue)에 쌓여 우선순위 높게 처리

6

  • microtask queue는 렌더링 전에 모두 비워지기 때문에 무거운 작업은 넣지 말아야 함
  • 만약 거대한 loop logic을 넣는다면 큐가 오랜 시간 비워지지 않아서 탭이 먹통될 수 있음
  • microtask의 목적은 상태 일관성, 렌더링 안정성이어야 함
  • 어울리는 작업은 상태 후처리, 로깅, 플래그 정리
  • 어울리지 않는 작업은 반복 계산, 애니메이션, 폴링
  • 무거운 작업은 macrotask에 양보하거나, requestAnimiationFrame, Worker 등을 활용

참고

console.log('a');
(async () => {
  console.log('a-b');
  setTimeout(() => console.log('t'), 1);
  await new Promise((resolve) => { resolve() });
  console.log('b');
})();
requestAnimationFrame(() => new Promise((res) => { res(); }).then(() => console.log('rt')));
requestAnimationFrame(() => requestAnimationFrame(() => new Promise((res) => { res(); }).then(() => console.log('rt2'))));
(async () => {
  await new Promise((resolve) => { resolve() });
  requestAnimationFrame(() => console.log('rt3'));
})();
requestAnimationFrame(() => setTimeout(() => console.log('t2'), 1));
console.log('c');
published 11 months ago · last updated 11 days ago