이벤트 루프(EventLoop)

Gunwoo Kim·2021년 8월 12일
1

자바스크립트 동작

자바스크립트를 공부하게 될 경우 많이 듣는 말이 있습니다.

자바스크립트는 단일 스레드 기반의 언어이며 Non-Blocking 또는 비동기 방식 이라는 말입니다.

단일 스레드

자바스크립트에서 큰 특징 중 하나인 단일 스레드 기반의 언어이며 스레드는 작업을 처리할 수 있는 공간이라고 한다면 단일이라는 의미는 하나의 작업만 처리할 수 있다는 말입니다.

그러나 막상 자바스크립트 언어를 공부하게 될 경우 실제로는 많은 작업이 동시에 처리되고 있는 것을 확인 할 수 있습니다.

// 즉시실행함수
(() => {
  console.log(1);
  setTimeout(()=>{
      console.log(2);
  },0)
  console.log(3);
})();

위에 즉시실행함수를 실행해보게 되면 기본적인 프로그램의 영역에서는 순서대로 1,2,3 으로 실행되어야 하지만 1,3,2 순으로 실행되는것을 확인 할 수 있습니다.

Non-Blocking

자바스크립트의 또 다른 특징으로는 Non-Blocking이라는 점 입니다.
앞의 예제에서 봤듯이 분명 setTimeout 함수를 실행했고 시간도 0초로 하여 순서상으로 바로 실행되도록 하였습니다.

그러나 실제 실행은 밑에 있는 함수까지 실행이 되고 실행이 되었습니다.

이때 등장하는 개념이 이벤트 루프입니다.
자바스크립트는 이벤트 루프를 이용해서 비동기 방식으로 동시성을 지원합니다.

이벤트 루프

그렇다면 여기서 이벤트 루프란 무엇일까?

MDN에서는 다음과 같이 정의합니다.

자바스크립트는 이벤트 루프에 기반한 동시성 모델이라고 한다. 이벤트 루프는 코드 실행과 collecting(이벤트 수집) and processing events(이벤트 처리), queued sub-tasks(큐에 놓인 하위 테스크) 실행을 담당한다.

좀 더 쉽게 정리하면 이벤트 루프는 task(작업)가 들어오길 기다렸다가 태스크가 들어오면 이를 처리하고, 처리할 태스크가 없는 경우엔 잠드는, 끊임없이 돌아가는 자바스크립트 내 루프입니다

위에서 단일 스레드라는 말이 나왔었는데, 여기서 메인 스레드하나의 이벤트 루프 하나의 콜스택이기 때문에 단일 스레드라고 부릅니다.

이벤트 루프 동작

여기서 알아야할 것은 자바스크립트 자체가 비동기로 동작을 지원하지 않는다는 것입니다.

실제 비동기를 처리는 자바스크립트가 아닌 브라우저가 처리합니다.

위 이미지를 보게되면 브라우저는 자바스크립트 엔진, Web APIs, Event Loop, Callback Queue등으로 구성되어있습니다.

자바스크립트 엔진

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

Memory Heap 은 메모리 할당이 일어나는 곳으로 선언한 변수, 함수 등이 담겨져 있습니다.
Call Stack 은 코드가 실행될 때 쌓이는 곳으로 *stack(스택) 형태로 쌓입니다.

*Stack(스택) : 자료구조 중 하나, 선입후출(LIFO, Last In First Out)의 룰을 따른다.

Web API

Wep API는 자바스크립트 엔진이 아닌 브라우저에서 제공하는 API 로 DOM, Ajax, Timeout 등이 있습니다.
Call Stack에서 실행된 비동기 함수는 Web API를 호출하고,
Web API는 콜백함수를 Callback Queue에 밀어 넣습니다.

Callback *Queue (콜백 큐)

비동기적으로 실행된 콜백함수가 보관 되는 영역입니다.
예를 들어 setTimeout이 Web API를 호출하고 호출된 setTimeout의 동작이 끝날 경우 Callback Queue를 호출합니다.
호출된 Callback Queue는 순서대로 쌓이며 쌓인 순서대로 실행됩니다.

Queue(큐) : 자료 구조 중 하나, 선입선출(FIFO, Frist In Frist OUT)의 룰을 따른다.

✅ Event Loop

Event LoopCall StackCallback Queue의 상태를 체크하여 Call Stack이 빈 상태가 되면, Callback Queue의 첫번째 콜백을 Call Stack으로 밀어넣는다.

위에 이벤트 루프 관련 좀 더 원할한 확인을 위해 loupe라는 사이트를 통해 확인해보도록 하겠습니다.

참고링크 : http://latentflip.com/loupe

위 이미지에서 보이듯이 자바스크립트 위에서 부터 순서대로 Call Stack 을 호출하게 되고 비동기 처리가 필요한 setTimeout의 경우 Web Apis를 호출하는것을 볼 수 있습니다.

Web Apis에서 지정된 시간이 끝날경우 Callback Queue 로 이동하게 되며 순서대로 쌓이는것을 확인 할 수 있습니다.

순서대로 쌓인 Callback QueueCall Stack이 빈 경우 순서대로 실행시키는 것을 확인 할 수 있습니다.

✅ Microtask Queue⁉️

추가적으로 이벤트 루프에 대해 찾아보던중 Microtask Queue라는 것을 알게 되었습니다.

console.log('script start'); 

setTimeout(function() {
  console.log('setTimeout');
}, 0);

Promise.resolve().then(function() {
  console.log('promise1');
}).then(function() {
  console.log('promise2');
});

console.log('script end');

자바스크립트 코드가 위와 같을 때 예상했던 결과는 아래와 같지만

script start
script end
setTimeout
promise1
promise2

실제 결과는 아래와 같습니다.

script start
script end
promise1
promise2
setTimeout

이때 Callback Queue에는 Task Queue, Microtask Queue라는 것이 존재하며 일반적인 Web APITask에 쌓이지만 PromiseMicrotask에 쌓이게 되며 동일하게 Task가 쌓였다고 했을때 Microtask => Task 순으로 Call Stack으로 이동하게 됩니다.

자바스크립트 비동기 처리 과정과 RxJS Scheduler에서 좀 더 자세히 알 수 있습니다.

참고링크
How JavaScript works: Event loop... :
https://blog.sessionstack.com/how-javascript-works-event-loop-and-the-rise-of-async-programming-5-ways-to-better-coding-with-2f077c4438b5
[JavaScript] Event loop와 call stack 은 어떻게 작동하나? :
https://www.youtube.com/watch?v=zi-IG6VHBh8
호출 스택과 이벤트루프 :
https://www.zerocho.com/category/JavaScript/post/597f34bbb428530018e8e6e2
자바스크립트와 이벤트 루프 :
https://meetup.toast.com/posts/89
이벤트 루프와 매크로·마이크로태스크 :
https://ko.javascript.info/event-loop
자바스크립트 비동기 처리 과정과 RxJS Scheduler :
https://sculove.github.io/post/javascriptflow/

0개의 댓글