[ JavaScript ] 이벤트 루프(Event Loop)

exceed_96·2024년 2월 3일

JavaScript

목록 보기
8/18
post-thumbnail

setTimeout, AJAX를 이용한 비동기 로직을 JavaScript는 해당 작업이 언제 끝날지 혹은 타이머가 다 지났는지를 어떻게 알고 로직을 실행시키는 걸까? 만약 위와같은 역할을 해주는 특정 엔진이나 요소가 있다면 싱글 스레드로 돌아가는 JavaScript외에 스레드 기반으로 동작하는 무언가가 있지 않을까?

이번 포스팅에서는 멀티 스레드처럼 동작할수도 JavaScript를 도와주는 무언가에 대해서 알아보자



1. Call Stack, Web API, Callback Queue

1.1 Call Stack

JavaScript는 Call Stack이라는 스택에 함수 실행 컨텍스트를 push하거나 pop하여서 전체 코드를 동작시킨다.

JavaScript Engine이 로직을 순회하면서 함수를 만난다면 해당 함수의 실행 컨텍스트를 생성해주고 변수들을 메모리에 정의해준 다음 해당 함수를 실행시키고 해당 함수가 리턴을 한다면 해당 함수 실행 컨텍스트를 Call Stack에서 제거해주는 방식이다.

만약 여기에 setTimeout이나 AJAX와 같은 비동기 로직이 들어가면 해당 로직이 끝나기 전까지 Call Stack에서 제거해주지 않고 무한정 기다리고 있을까?

아래 예시 코드를 살펴보자

console.log("code start");

setTimeout(() => {
  console.log("hello Timer");
}, 1000);

console.log("code end");

위 결과물을 보면 setTimeout을 무한정 기다리는게 아닌 나머지 로직을 먼저 순회한 후 setTimeout의 콜백함수가 실행된걸 확인할 수 있다.

그럼 왜 이런 결과가 나타난걸까?



1.2 Web API

우리는 JavaScript에서의 관점이 아닌 브라우저의 관점에서 위 로직을 살펴볼 필요가 있다.

싱글 스레드인 JavaScript가 멀티스레드 처럼 동작하는 이유에는 Web API이라는 웹 브라우저 애플리케이션의 역할을 살펴봐야 한다.

Web API는 다양한 메서드들로 구성된 API이다.

DOM, AJAX, Timeout, Canvas 등등 다양한 메서드들로 구성되어 있는데 해당 메서드들은 각각 하나의 스레드로 동작한다.

즉, setTimeout, AJAX등등을 사용하면 비동기로직으로 동시에 처리되는 즉, 멀티스레드와 같은 모습을 보여주는 이유는 JavaScript의 싱글스레드 말고도 Web API의 스레드 들이 해당 로직을 처리해줘서 동시에 처리가 가능한 것이다.

즉 setTimeout로직을 사용했다면 해당 콜백함수와 타이머 정의를 Web API로 이동시킨다.

이동한 타이머는 Web API에서는 비동기로 타이머를 동작시켜서 지정한 시간만큼 시간을 카운트한다.

정의한 시간만큼 시간이 소요됐다면 해당 콜백함수를 Callback Queue에 옮겨준다.

그럼 여기서 Callback Queue의 역할은 뭘까?

특정 영상이나 글에서는 Web API의 모든 메서드들이 비동기적으로 작동한다는 글이 있는데 모든 Web API가 아니다. 예를들어 Canvas는 비동기가 아닌 동기적으로 동작한다.



1.3 Callback Queue

Callback Queue는 Web API에서 사전 정의한 처리가 끝난 콜백함수를 받는 Web API로 부터 받아서 저장하는 곳이다.

크게 MicroTask Queue, Task Queue로 구성되어 있다.


1.3.1 MicroTask Queue

MicroTask Queue에는 주로 AJAX의 데이터 후처리에 관련된 Promise.then, Promise.catch같은 콜백함수가 들어간다.


1.3.2 Task Queue

Task Queue에는 주로 setTimeout, setInteraval, Event Handler, fetch의 콜백함수가 들어간다.


그럼 MicroTask Queue, Task Queue의 차이는 뭘까?

여기서 먼저 알아야 할 점은 해당 콜백함수들은 말그대로 함수이다.

즉, 콜백함수들은 Call Stack에 push되어서 실행 컨텍스트를 생성하고 해당 실행컨텍스트를 동작시킨다.

주의해야 할 점은 Call Stack에 바로바로 넣어주는게 아닌 Call Stack이 다 비워지고 난 다음에 Callback Queue에 있던 콜백함수가 Call Stack에 들어간다.

이 동작원리를 알고나면 왜 setTimeout함수는 로직상의 모든 코드가 동작한 다음에 동작하는지에 대해 이해 할 수 있다.


console.log("code start");

setTimeout(() => {
  console.log("hello Timer");
}, 0);

console.log("code end");

만약 위 처럼 setTimeout의 타이머를 0으로 지정하면 어떻게 될까?

위와같이 Callback Queue에 들어있는 0초로 정의했다고 해서 콜백함수가 Call Stack에 바로 들어가는게 아닌 모든 로직이 끝난 다음에 Call Stack에 들어가서 실행된다는걸 확인할 수 있다.


다시 본론으로 돌아와서 MicroTask Queue, Task Queue의 차이가 뭔지 살펴보자


console.log("code start");

const promiseResult = Promise.resolve("Hello Promise").then((res) => {
  console.log(res);
});

setTimeout(() => {
  console.log("hello Timer");
}, 0);

console.log("code end");

위와같이 MicroTask Queue, Task Queue에 각각의 콜백함수를 넣기 위해서 Promise.then로직 하나랑 setTimeout로직 하나를 정의해보자

과연 결과가 어떻게 출력될까?

위와같이 Promise.then이 먼저 실행돼고 setTimeout이 나중에 실행된거 확인할 수 있다.

즉, Call Stack가 비워졌다면 MicroStack Queue에 들어있던 콜백함수가 들어간 순서대로 Call Stack에 먼저 들어가고 그 이후에 Task Queue에 들어있던 콜백함수가 들어가는 것이다.


JavaScript에서의 비동기 로직 처리는 위와같이 웹 브라우저의 Web API, CallBack Queue, Call Stack을 지나가는 과정을 통해서 로직이 실행돼고 싱글스레드인 JavaScript를 멀티스레드처럼 동작하게 해주게 되는 것이다.

그럼 다시 타이틀로 돌아와서 대체 Event Loop가 뭐길래 사전설명이 길었던 걸까?



2. 이벤트 루프(Event Loop)

그럼 여기서 드는 의문은 "그럼 누가 콜백함수를 옮겨주고 또 Web API으로 타이머랑 콜백함수 등등을 옮겨주는 주체가 누구인거야?라는 생각을 하게 된다.

바로 이 역할을 해주는 주체는 이벤트 루프인 것이다.


위 그림과 같이 비동기 함수 작업을 Web API에 옮기고 해당 콜백함수를 Callback Queue에 옮기고 Call Stack에 옮기는 역할만을 하는 것이다.

즉, 일종의 관리자 역할을 한다.



3. 마치며

"JavaScript는 싱글스레드 기반의 언어인데 어떻게 멀티스레드처럼 동작하는걸까? 멀티스레드의 역할을 하는 주체가 있다면 해당 주체는 무엇일까?"라는 의문을 가지고 이번 포스팅을 시작해서 이벤트루프까지 애매하게 알고있었던 지식을 깊게 이해한 포스팅 주제였다.

사실 위 설명보다 더욱 더 딥 다이브한 내용들이 많고
물론 위의 예시들은 아주 간단한 케이스들이라 해당 플로우를 눈으로 읽어가기 쉽지만 프로젝트의 규모가 커지고 비동기 로직이 많아진다면 해당 개념을 적응하는데 꽤 시간이 걸릴거 같지만 어차피 알아야 할거 제대로 이해하고 가야겠다.



4. Reference

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://www.youtube.com/watch?v=v67LloZ1ieI
https://www.youtube.com/watch?v=wcxWlyps4Vg

profile
개발진행형

0개의 댓글