코린이의 개발 일지

[브라우저] 이벤트 루프를 살펴보자 본문

웹 (web)

[브라우저] 이벤트 루프를 살펴보자

폴라민 2023. 1. 25. 00:08
반응형

이벤트 루프란?

  • 자바스크립트 자체는 싱글 스레드로 동작한다.
  • 하지만 브라우저가 동작하는 것을 살펴보면 여러 태스크가 동시에 처리된다.
  • 이처럼 자바스크립트의 동시성을 지원하는 것이 바로 이벤트 루프이다.
  • 이벤트 루프는 브라우저에 내장되어 있는 기능 중 하나이다. (Node.js도 이벤트 루프 기반으로 동작한다)

 

브라우저 환경에서 동작 과정

그림을 보면 자바스크립트 엔진은 크게 두개로 나뉘어져 있다.

  • 콜스택: 소스코드 평가 과정에서 생성된 실행 컨텍스트가 추가되고 제거되는 스택
  • 힙: 객체가 저장되는 메모리 공간. 콜 스택의 요소인 실행 컨텍스트는 힙에 저장된 객체를 참조한다.

자바스크립트 엔진은 단순하게 태스크가 요청되면 콜스택을 통해 요청 받은 작업을 순차적으로 실행한다. 즉, 비동기 처리에서 소스코드 평가와 실행을 제외한 모든 처리는 자바스크립트 엔진을 구동하는 환경인 브라우저, 혹은 Node.js가 담당한다.

 

 

예를 들어보자.

function foo(){
	console.log('foo');
}

function bar(){
	console.log('bar');
}

setTimeout(foo, 0);
bar();

위의 코드 동작 순서를 차례대로 살펴 보면

  1. 전역 코드가 평가 되어 전역 실행 컨텍스트가 생성되고 콜스택에 푸쉬
  2. 전역 코드 실행
    1. setTimeout 함수 호출
    2. setTimeout 함수의 함수 실행 컨텍스트가 생성되고 콜스택에 푸쉬
  3. setTimeout 함수 실행
    1. 콜백 함수 호출 스케줄링
    2. 종료, 콜스택에서 팝
  4. 이 단계에서 브라우저와 자바스크립트 엔진이 각각 자기가 맡은 역할을 한다 ⇒ 즉 병렬 처리된다.
    1. 브라우저: 호출스케줄링을 담당한다.
      1. 타이머 설정 후, 타이머 만료를 기다린다.
      2. 티이머가 만료되면 콜백함수 foo를 태스크 큐에 푸쉬
    2. 자바스크립트 엔진: 다음 소스코드 실행
      1. setTimeout함수 실행이 종료되었음으로 다시 전역 코드 실행으로 돌아가서 다음 소스코드를 실행한다.
      2. 다음 소스코드인 bar()를 실행
      3. bar함수가 호출 되어 bar 함수 실행 컨텍스트 생성 후 콜 스택에 푸쉬
      4. bar함수 실행이 종료되면 콜스택에서 팝
  5. 전역 코드 실행 종료, 전역 실행 컨텍스트 콜 스택에서 팝
  6. 이벤트 루프에 의해 콜 스택이 비어 있음 감지. 태스크 큐에 foo함수가 대기중이므로, 대기 중인 foo함수의 함수 실행 컨텍스트를 생성하고 콜스택으로 푸쉬
  7. foo함수 실행 후 종료, 콜스택에서 팝

 

 

한마디로 setTimeout의 콜백 함수의 평가와 실행은 자바스크립트 엔진이 담당하지만, 호출 스케줄링을 위한 타이머 설정과 콜백 함수의 등록은 브라우저가 담당한다.

 

 

이벤트 루프 역할

  • 이벤트 루프는 콜 스택에 현재 실행 중인 실행 컨텍스트가 있는지, 그리고 태스크 큐에 대기 중인 함수가 있는지 반복해서 확인
  • 콜 스택이 비어 있고 태스크 큐에 대기 중인 함수가 있다면 이벤트 루프는 순차적(FIFO)으로 태스크 큐에 대기 중인 함수를 콜 스택으로 이동

이때 콜스택으로 이동한 함수는 자바스크립트 엔진에 의해 실행된다.

 

 

최종 정리

  • 이벤트 루프와 태스크 큐는 브라우저 환경이 제공한다.
  • 싱글 스레드 방식으로 동작하는 것은 브라우저가 아닌 브라우저에 내장된 자바스크립트 엔진이다. 브라우저는 멀티 스레드로 동작한다.
  • 브라우저가 단일 호출 스택을 사용하는 자바스크립트 엔진과 상호 연동하기 위해 사용하는 장치가 바로 ‘이벤트 루프’이다.
  • 이벤트 루프는 콜 스택에 현재 실행 중인 실행 컨텍스트가 있는지, 그리고 태스크 큐에 대기 중인 함수가 있는지 반복해서 확인한다.
    • 이때 태스크 큐가 비어있다면 이벤트 루프는 새로운 태스크가 태스크 큐에 추가될 때까지 대기한다.
  • 콜 스택이 비어 있고 태스크 큐에 대기 중인 함수가 있다면 이벤트 루프는 순차적(FIFO)으로 태스크 큐에 대기 중인 함수를 콜 스택으로 이동시킨다.

 

 

추가 공부해볼 사항

  • 마이크로 태스크와 일반 태스크의 차이점
  • Node.js환경과 브라우저 환경의 이벤트 루프 상세 구현이 조금씩 다르다고 한다.(심지어 브라우저 별로도 구현이 조금씩 다름)
  • ES6에 Promise랑 Job queue라는 항목이 추가되었는데 이벤트 루프 큐랑 뭐가 다른지?
  • What is the difference between "event loop queue" and "job queue"?

 

 

Refs.

  • 모던 자바스크립트
    • 23장 실행 컨텍스트 (359p - 366p)
    • 42.2장 이벤트 루프와 태스크 큐 (812p - 815p)

자바스크립트와 이벤트 루프 : NHN Cloud Meetup

 

자바스크립트와 이벤트 루프 : NHN Cloud Meetup

자바스크립트와 이벤트 루프

meetup.nhncloud.com

The event loop - JavaScript | MDN

 

The event loop - JavaScript | MDN

JavaScript has a runtime model based on an event loop, which is responsible for executing the code, collecting and processing events, and executing queued sub-tasks. This model is quite different from models in other languages like C and Java.

developer.mozilla.org

이벤트 루프와 매크로태스크, 마이크로태스크

반응형
Comments