Posts 이벤트 루프
Post
Cancel

이벤트 루프

자바스크립트는 이벤트 루프에 기반한 동시성(concurrency) 모델을 가지고 있다.

자바스크립트에서 호출된 함수는 콜 스택(Call Stack) 으로 푸쉬되어 처리 되는데, 단일 콜 스택을 사용하기 때문에 (자바스크립트가 싱글 쓰레드라고 얘기되는 것은 이 부분과 연관된다.) 현재 콜 스택으로 푸쉬 된 함수에서 어떤 이벤트를 처리하기 위해 이벤트의 발생을 대기하거나, 응답을 기다리게 된다면 모든 작업이 block 되어 버린다.

다행히 브라우저 또는 Node.js 등의 자바스크립트 런타임 환경은 멀티 쓰레드가 가능하기 때문에 비동기 API (타이머, 이벤트 리스너, FileReader, HTTP 요청 등)를 제공하고 있으며 이를 사용하여 비동기, 논블로킹을 구현할 수 있다.


백그라운드에서 처리가 완료된 작업의 콜백 함수는 콜백 큐(Callback Queue) 로 이동되는데 이벤트 루프는 콜 스택을 확인하여 콜 스택이 완전히 빈 상태가 되면 콜백 큐에 있는 작업을 콜 스택으로 이동시킨다.


아래의 코드와 이미지를 통해 자바스크립트의 코드 실행 과정과 이벤트 루프가 어떻게 동작하는지 확인해 볼 수 있다.

1
2
3
4
5
6
7
const foo = () => console.log('First');
const bar = () => setTimeout(() => console.log('Second'), 500);
const baz = () => console.log('Third');

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

gif14.1.gif

_이미지 출처: https://dev.to/lydiahallie/javascript-visualized-event-loop-3dif_


위의 코드는 다음과 같은 과정으로 실행된다.

  1. bar() 함수가 호출되어 콜 스택에 푸쉬되고, 반환 값인 setTimeout() 함수가 콜 스택에 푸쉬되어 실행된다.
  2. 백그라운드에서 타이머가 실행되고, setTimeout(), bar() 함수가 콜 스택에서 빠져나온다. (타이머가 끝나면 콜백 함수를 콜백 큐로 이동시킨다.)
  3. foo() 함수가 호출되어 콜 스택에 푸쉬되고, “First” 를 출력한 다음 콜 스택에서 빠져나온다.
  4. baz() 함수가 호출되어 콜 스택에 푸쉬되고, “Third” 를 출력한 다음 콜 스택에서 빠져나온다.
  5. 콜 스택이 빈 상태가 되어, 이벤트 루프는 콜백 큐에 있던 콜백 함수를 콜 스택으로 푸쉬한다.
  6. “Second” 를 출력하고, 콜백 함수는 콜 스택에서 빠져나온다.


2. Context

이벤트 루프에 대해 공부하면서 한가지 헷갈렸던 부분은 어떤 함수가 콜 스택으로 푸쉬되어 실행된 다음 빠져나오면 콜 스택은 빈 상태가 되는데, 이벤트 루프는 실행할 함수가 더 존재하는 빈 상태와, 실행할 함수가 더이상 존재하지 않는 빈 상태를 어떻게 구분하는가였다.

이 부분에 대한 해답은 Context 에 있었다.


2-1) Global Execution Context

가장 처음 코드가 실행되면 자바스크립트 엔진에서 전역 실행 컨텍스트를 생성하여 콜 스택에 푸쉬한다.

전역 실행 컨텍스트에서는 다음 작업을 진행한다.


creation phase

  1. 전역 객체를 생성 (브라우저에서는 window, node.js 에서는 global 객체가 생성된다.)
  2. this 객체를 생성하고 전역 객체와 바인딩한다.
  3. 변수와 함수의 선언을 메모리 힙에 저장하고 변수를 undefined 로 초기화 한다.


execution phase

코드를 한줄씩 읽으며 변수에 값을 할당하거나, 함수를 호출한다.


2-2) Function Execution Context

전역 컨텍스트에서 코드를 실행하다가 함수가 호출되면 함수 실행 컨텍스트를 생성하여 콜 스택에 푸쉬한다.

함수 실행 컨텍스트는 전역 객체 대신 함수에 전달 된 모든 매개 변수에 대한 참조를 포함하는 arguments 객체를 생성한다는 점을 제외하면 전역 실행 컨텍스트와 같은 작업을 진행한다.


2-3) 콜 스택의 빈 상태란?

전역 실행 컨텍스트는 main() 또는 global() 이란 함수로 콜 스택에 가장 먼저 푸쉬되고, 모든 코드를 읽어서 실행을 완료하기 전까지 콜 스택에 남아있게 된다. 즉, 콜 스택이 완전히 비어있다는 것은 전역 실행 컨텍스트까지 종료되었다는 것을 의미하며, 콜백 큐의 작업들은 전역 실행 컨텍스트가 종료되기 전까지 대기하게 된다.


JavaScript-Call-Stack.png

_이미지 출처: [https://www.javascripttutorial.net/javascript-call-stack/](https://www.javascripttutorial.net/javascript-call-stack/)


참고자료

https://dev.to/lydiahallie/javascript-visualized-event-loop-3dif

https://www.javascripttutorial.net/javascript-execution-context/

https://www.zerocho.com/category/JavaScript/post/597f34bbb428530018e8e6e2

This post is licensed under CC BY 4.0 by the author.

클래스

Promise

Comments powered by Disqus.