Event loop

zenoan·2021년 4월 3일
0

Javascript Engine

Javascript를 해석하는 Javascript engine과 web browser에 화면을 그리는 rendering engine은 다른 것이다. 브라우저에서는 V8 엔진, 서버에서는 node.js가 있다.
V8엔진에서는 Call stack, Task Queue, Heap으로 나뉘고 Event loop라는 것이 Task(Callback) Queue에 들어가는 task들을 관리하게 된다.
자바스크립트 엔진과 그 실행 환경을 상호 연동시켜주는 장치가 바로 event loop다. 따라서, 이벤트 루프는 자바스크립트 엔진에 있지 않고 그 환경에 속한다.

Call stack

  • Javascript는 단 하나의 호출 스택(call stack)을 사용.
  • 함수가 실행되는 방식 "Run to completion". 하나의 함수가 실행되면 이 함수의 실행이 끝날 때까지 다른 task 수행될 수 없다.
  • 요청이 들어올 때마다 해당 요청을 순차적으로 호출 스택에 담아 처리한다.
  • 메소드가 실행될 때, call stack에 새로운 프레임이 생기고 push되고 메소드의 실행이 끝나면 pop된다
function foo(b) {
  var a = 10;
  return a + b;
}

function bar(x) {
  var y = 2;
  return foo(x + y);
}

console.log(bar(1));
  • bar 함수 호출. bar에 해당하는 stack frame 형성. y local variable 생성.
  • bar 함수는 foo 함수 호출. bar 함수는 종료되지 않아서 pop이 안된다.
  • foo 함수가 call stack에 push.
  • foo 함수에서는 a+b 라는 값을 return 하면서 함수가 끝나고, stack에서 pop된다.
  • bar 함수로 돌아와서 foo 함수로부터 받은 값을 return 하면서 bar 함수도 끝나고 pop된다.

Heap

동적으로 생성된 객체는 heap에 할당

Task Queue

  • Javascript runtime environment에서는 처리해야 하는 task들을 임시 저장하는 대기 queue가 존재.
  • 그 대기 queue는 task queue라고 하고 call stack이 비어졌을 때 먼저 대기열에 들어온 순서대로 수행된다.
setTimeout(function() {
  console.log('first');
}, 0);
console.log('second');
// 콘솔:
// second
// first

Javascript에서 비동기로 호풀되는 함수들은 call stack에 쌓이지 않고 task queue에 enqueue된다. Javascript에서는 event에 의해 실행되는 함수들이 비동기로 실행된다.

Task queue & Microtask queue

자바스크립트의 실행 환경은 2가지 큐를 가지고 있으며 각각 스크립트 실행, 이벤트 핸들러, 콜백함수 등의 task가 담기는 공간이다. Task가 콜백함수라면 그 종류에 따라 다른 큐에 담기며 대표적인 예로는 다음과 같은 것들이 있다.

  • Task queue
    • setTimeout() , setInterval() , UI 렌더링, requestAnimationFrame()
  • Microtask queue
    • Promise, MutationObserver

Event loop는 2개의 queue를 감시하고 있다가 call stack이 비게 되면, 콜백함수를 꺼내와서 실행한다. 이 때 microtask queue의 콜백함수가 우선순위를 가진다.
Microtask queue의 콜백함수를 전부 실행하고 나서 task queue의 콜백함수들을 실행한다. (UI 렌더링이 task queue에 속하기 때문에 microtask queue의 task가 많으면 rendering이 지연될 수 있다.)

console.log('call stack');
setTimeout(() => console.log('task queue!'), 0);
Promise.resolve().then(() => console.log('microtask queue'));
//콘솔:
// call stack
// microtask queue
// task queue
profile
프론트엔드 개발자

0개의 댓글