Event Loop

June 10, 2022

이벤트 루프 동작 원리


들어가기 전

이벤트 루프를 보기 전 자바스크립트에 대해 짚어보자면

자바스크립트는 싱글 스레드 언어이다.

하나의 콜 스택을 가진다. 이는 한번에 하나의 일만 처리할 수 있다는 의미이다.

위의 내용을 전제로 자바스크립트 엔진을 간단히 보면

eventloop-1.png

자바스크립트 엔진은 Memory HeapCall Stack으로 구성되어있다.


Memory Heap

메모리 할당이 일어나는 부분으로 코드에서 선언한 변수, 객체 등이 저장된다. 즉 창고의 역할을 한다.

Call Stack

Call Stack 코드가 쌓이는 장소이며 후입선출(Last In First Out)의 구조를 가진다.

실행된 자바스크립트 코드는 순서대로 stack에 쌓인 뒤 위에 쌓인 함수부터 처리한다.

(순서대로 처리 → 동기적 처리를 의미)

자바스크립트는 싱글스레드이기 때문에 여러 일을 한번에 처리할 수 없다.

하지만 브라우저의 web APIs들을 사용하여 멀티 스레드인 것처럼 비동기적인 작업이 가능하다.

이때 등장하는 개념이 Event Loop이다.

Event Loop를 설명하기 위해

자바스크립트 엔진과 브라우저의 web APIs가 만나 처리되는 과정을 살펴볼 필요가 있다.

web APIs

Chrome, Safari와 같은 브라우저에서 제공하는 API로 DOM, AJAX, Timeout 등이 있다.

call stack에 쌓여 있는 비동기 함수들은 DOM, AJAX, Timeout 등과 같은 web APIs를 호출하고,

web APIs는 비동기 함수를 Callback Queue에 넣는다.

Callback Queue (=task Queue라고도 불린다.)

web APIs로 부터 전달 받은 비동기 함수들이 보관되어 있는 장소이다.

Queue는 선입 선출의 의미를 가지는데 가장 먼저 들어온 함수부터 처리한다.

처리한다는 의미는 Callback Queue에서 Call Stack으로 비동기 함수를 보낸다는 것이다.

보내는 과정을 Event Loop라 한다.


Event Loop

eventloop-2.png

Event Loop는 Call Stack과 Callback Queue의 상태를 계속 주시한다.

Call Stack에서 더이상 작동할 함수가 없다면 (= Call Stack이 비어있다면) Callback Queue에 먼저 들어온 순서대로 비동기 함수들을 Call Stack으로 이동시킨다.

핵심은 Call Stack이 비어있는 경우Callback Queue에 들어온 순서대로 동작 하는 과정이다.


동작과정

  • 코드를 실행했을 때 Call Stack에 먼저 쌓이게 되고
  • setTimeout과 같은 webapi를 만났을 때 이를 태스크 큐에 넣어 둔다.
  • Call Stack이 후입 선출의 방식으로 쌓여놓은 함수들을 모두 처리하여 Call Stack이 비었을 때
  • Callback Queue에 있는 함수들은 Call Stack으로 옮겨지고 처리된다.
  • 옮기는 과정을 Event Loop라 한다.

코드 예시

일반적인 자바스크립트 동작 방식

function printHello(name) {
  hello(name)
  welcome()

  return 0
}

// 함수 선언식은 호이스팅이 되기 때문에 위에서 함수 사용이 가능하다. 
function hello(name) {
  console.log(`hello ${name}!`)
}

function welcome() {
  console.log('welcome!')
}

printHello('Ana')
// console에 찍히는 결과 

// hello Ana!
// welcome!
// 0

비동기 처리가 적용된 자바스크립트 동작 방식

function printHello(name) {
  setTimeout(() => {
    hello(name)
  }, 0) // defer hello

  welcome()

  return 0
}

function hello(name) {
  console.log(`hello ${name}!`)
}

function welcome() {
  console.log('welcome!')
}

printHello('Ana')
// console에 찍히는 결과 

// welcome!
// 0
// hello Ana!

	// setTimeout은 Callback Queue로 이동하여 Call Stack이 비워졌을 때 
	// queue에서 stack으로 이동하기 때문에 마지막에 실행된다. 

정리

처음으로 돌아가서, 싱글 스레드이기 때문에 동기적인 처리밖에 할 수 없었던 자바스크립트는

브라우저의 web APIs, Callback Queue, Event Loop의 사용으로 인하여

멀티 스레드인 것처럼 비동기적으로 작동할 수 있게 된 것이다.


참조

https://cloudoki.com/js-dont-block-the-event-loop/

https://blog.sessionstack.com/how-does-javascript-actually-work-part-1-b0bacc073cf

https://www.youtube.com/watch?v=8aGhZQkoFbQ&ab_channel=JSConf