JavaScript

[JavaScript] Event Loop

프론트로그 2023. 8. 3. 03:18

자바스크립트를 잘 사용하기 위해서 알아야 하는 핵심 개념들이 있는데 

싱글 스레드 언어인 자바스크립트의 동작 과정을 이해하기 위해 알아야 하는 개념인

Event Loop 에 대해서 알아보자! 😁

 

 

1. Event Loop 가 뭐지? 🤔

 

이벤트 루프? 처음 들었을때 이게 뭐지? 라는 생각부터 먼저 들었다 😵 생소한 단어라 가장 먼저 떠올린 단어는

Event Horizon 우리말로 사건의 지평선이 제일 먼저 떠올라 무슨 과학 용어 인줄 알았다.

 

Event Loop 란 딱 뭐라고 정의된 표현은 찾지 못했지만 내가 이해한 바로는 자바스크립트 엔진 내에 실행되어있는

프로그램 내지는 프로세스? 라고 정의 할 수 있다.

 

Event Loop 는 싱글 스레드 언어인 자바스크립트가 효율적인 동작을 할 수 있도록 자바스크립트 엔진에 있는 콜스택, 이벤트 큐, 마이크로태스크 큐 를 감시하면서 콜스택이 비었을때 이벤트,마이크로태스크 큐에 대기하고 있는 비동기 동작들을 콜 스택으로 넘겨 처리 해 효율적인 처리를 관리한다.

 

아래 이미지를 통해 이벤트 루프가 어떻게 생겨먹었는지 알아보자!

Event Loop의 동작 구조

 

그림을 보면 Stack 과 Callback Queue 사이에서 돌고 있는 Event Loop를 볼 수 있다.

 

💡 Callback Queue 는 Event Queue 와 Microtask Queue로 구분되어있다.

2. Event Loop 의 동작 원리 🔧

 

Event Loop의 동작을 알기 위해선 먼저 위 그림에서 본 각 컴포넌트들이 무슨 일을 하는지 알아야 한다.😋

Event Loop 는 콜 스택, 이벤트 큐, 마이크로 태스크 큐 세가지의 컴포넌트들로 이루어져 있다.

아래는 각 컴포넌트 들이 무슨일을 하는지에 대한 설명이다.

 

1. 콜 스택 (Call Stack)

  • 동기 작업에 대한 함수 호출을 저장하고 처리, 자바스크립트는 콜 스택을 사용하여 코드에서의 함수 호출을 추적하며, 호출된 코드를 차례대로 실행할 수 있다.

2. 이벤트 큐 (Event Queue)

  • 비동기 작업, 예를 들어 타이머 이벤트 (setTimeout, setInterval) 및 DOM 이벤트 등의 콜백 함수를 저장하고 처리한다.

3. 마이크로 태스크 큐 (Microtask Queue)

  • 비동기 작업 중 Promise와 관련된 콜백 함수 (then, catch, finally), MutationObserver, 그리고 Node.js 환경에서의 process.nextTick 등을 저장하고 처리한다.

 

이벤트 루프의 각 컴포넌트들의 역할이 무엇인지 알아봤으니 자바스크립트 엔진이 코드를 처리하는 순서를 그림과 코드로 살펴보자면

const foo = () => console.log("First");
const bar = () => setTimeout(() => console.log("Second"), 500);
const baz = () => console.log("Third");

bar();
foo();
baz();

이벤트 루프의 동작 과정

 

  1. 자바스크립트 엔진이 위에서 아래로 코드를 읽어가면서 동기 함수실행문 bar()를 먼저 발견하고 콜스택에 넣고 실행하면 안에 있던 web api 인 setTimeout를 호출 하고 콜스택에서 bar를 제거한다.
  2. Web api 에서는 호출 받은 setTimeout의 동작을 수행하고 입력받은 시간이 지나면 콜백 큐에 넘겨받은 콜백을 메세지 형태로 넘긴다. 
  3. foo() 실행을 발견하고 foo()를 콜스택에 넣고 실행하면 콘솔로그에 'First'가 나오고 foo를 콜스택에서 제거한다.
  4. 그 다음 실행문인 baz()를 발견 하고 baz를 실행 하면 콘솔로그에 'Third'가 찍혀 나온다.
  5. 모든 함수를 실행한 콜 스택이 비어있는걸 감지한 Event Loop가 콜백 큐에서 대기하고 있던 foo에서 넘겨받은 콜백 함수를 콜스택에 넘겨 실행한다.
  6. 콜백 큐에 있던 콜백을 넘겨 받은 콜스택은 콜백을 실행하고 콘솔에 'Second'가 찍혀 나온다.
  7. 모든 동작을 완료 했을때 콘솔에는 'First' , 'Third' , 'Second' 순서로 실행결과가 나온다.

여기서 대충 코드의 동작 과정을 보면서  Event Loop 의 동작을 이해한거 같은데 갑자기 Web API 라는게 등장한다.

 

💡 Web API 란?

Web API는 웹 브라우저와 같은 웹 플랫폼에서 제공하는 기능들의 집합으로, 자바스크립트 개발자가 웹 애플리케이션에서 사용할 수 있는 여러 인터페이스들을 제공합니다. 이를 통해 개발자들은 웹 페이지의 내용을 동적으로 변경하거나, 페이지 상호작용, 데이터 저장, 데이터 통신 등 다양한 기능을 사용할 수 있습니다.
 
Web API는 다음과 같은 기능을 제공합니다:

DOM (문서 객체 모델) 관련 API: 웹 페이지의 HTML 요소를 선택, 추가, 제거, 수정할 수 있게 해주는 API입니다. (예: getElementById, querySelector, appendChild, removeChild 등)XHR (XMLHttpRequest) 및 Fetch API: 서버와 데이터를 교환하고, 비동기 요청을 처리할 수 있는 API입니다.

이벤트 관련 API: 사용자 입력(키보드, 마우스), 타이머 설정, DOM 이벤트 등을 처리할 수 있는 API입니다. (예: addEventListener, setTimeout, setInterval 등)Web Storage API: 웹 브라우저에 데이터를 저장할 수 있는 로컬 스토리지와 세션 스토리지 API를 제공합니다.Geolocation API: 사용자의 현재 위치 정보를 얻을 수 있는 API입니다.

Web Workers API: 별도의 스레드에서 스크립트를 실행할 수 있는 멀티스레딩 기능을 제공하는 API입니다.Websockets API: 실시간 양방향 통신이 가능한 API로, 브라우저와 서버 간에 연결을 유지하고 데이터를 전송합니다.WebRTC API: 웹 브라우저 상에서 음성 및 비디오 통화 기능을 제공하는 API입니다.
이 외에도 많은 Web API들이 있으며, 웹 개발을 할 때 다양한 기능을 활용하여 사용자와의 상호작용 및 데이터 처리를 할 수 있습니다. 이들 API는 웹 애플리케이션을 더욱 풍부하게 만들어주고, 웹 개발의 기능 및 성능을 향상시킵니다.

위 설명에도 나와 있듯이 브라우저에서 제공하는 기능인데 자바스크립트 엔진과는 별도로 비동기 함수, 이벤트 API 등을 처리 하는 공간이 따로 있다.

 

자바스크립트는 브라우저 백그라운드에서 실행되는 Web API 를 통해서 비동기 작업을 수행한다.

 

즉 콜스택은 비동기 함수가 스택에 들어오면 직접 처리하는 것이 아니고 호출만 한 다음 Web API 에 비동기 함수의 처리를 맡기고 Web API 는 비동기 함수를 처리하고 나온 콜백 함수를 종류에 맞게 마이크로 태스크 큐 혹은 이벤트 큐에 넘기고 이벤트 루프는 이를 감지해서 콜스택이 비었을때 이런 콜백큐에 대기하고 있는 함수들을 콜스택으로 올려 처리하는 방식이다.

 

정리하자면

  1. 자바스크립트 엔진에서 코드를 실행하면서 동기 작업들은 콜 스택에서 처리된다.
  2. 비동기 작업(예: setTimeout, fetch, addEventListener 등)은 Web API 영역에서 처리된다.
  3. 비동기 작업이 완료되면 콜백 함수들은 마이크로태스크 큐 또는 이벤트 큐에 추가된다.
  4. 마이크로태스크 큐 가 이벤트 큐 보다 우선순위가 더 높다.
  5. 이벤트 루프는 콜 스택이 비어있을 때마다 마이크로태스크 큐와 이벤트 큐를 확인하고, 우선순위가 높은 마이크로태스크 큐의 콜백 함수를 콜 스택에 먼저 추가해 실행하고, 이벤트 큐의 첫 번째 콜백 함수를 콜 스택에 추가해 실행한다.
  6. 이 과정을 반복하여 자바스크립트는 비동기 작업을 처리한다.
  7. 이 과정을 Event Loop를 통해서 한다고 할 수 있다.

잘 이해가 안된다면 

이벤트 루프 동작확인

이 사이트에서 코드를 입력하고 동작을 확인 해보자

 

참고 블로그 : https://baeharam.netlify.app/posts/javascript/event-loop