티스토리 뷰

공부

이벤트 루프와 태스크 큐

코딩하는 둥아 2023. 1. 23. 15:36
728x90

 

태스크 큐는 콜백 함수들이 대기하는 큐(FIFO) 형태의 배열이라 할 수 있고,
이벤트 루프는 호출 스택이 비워질 때마다 태스크 큐에서 콜백 함수를 꺼내와서 실행하는 역할을 한다.

 

자바스크립트

  • 싱글스레드 기반의 언어로 한 번에 하나의 작업만을 처리할 수 있다.
  • 비동기로 동작하기 때문에 싱글스레드임에도 동시에 많은 작업을 처리할 수 있다.
  • 하지만 비동기로 동작하는 핵심 요소는 자바스크립트가 아닌 브라우저가 가지고 있다.

자바스크립트 엔진이 단일 호출 스택을 사용하기는 하지만, 자바스크립트가 구동되는 환경(브라우저, Node.js등)에서는 주로 여러 개의 스레드가 사용되며, 이러한 구동 환경이 단일 호출 스택을 사용하는 자바스크립트 엔진과 상호 연동하기위해 사용하는 장치가 바로 이벤트 루프이다.

 

메모리 힙 (Memory Heap)

객체가 저장되는 메모리 공간을 의미한다. 콜 스택의 요소인 실행 컨텍스트는 힙에 저장된 객체를 참조한다.

 

콜 스택 (Call Stack)

함수를 호출하면 함수의 인수와 지역 변수를 포함하는 프레임 스택을 형성하여 콜 스택에 푸쉬되고, 가장 위에 쌓인 함수부터 순차적으로 먼저 처리한다. (LIFO, Last In First Out)

자바스크립트는 싱글 스레드로 하나의 call stack을 사용하기 때문에 실행 컨텍스트가 종료되어 콜 스택에서 제거되기 전까지는 다른 태스크를 실행시키지 않는다. 

 

Web APIs

Web API는 브라우저에서 제공하는 API로 DOM, Ajax, TimeOut등이 있다.

CallStack에서 실행된 비동기 함수는 Web API를 호출하고, Web API는 콜백 함수를 Task Queue에 넣는다.

 

태스크 큐 (Task Queue)

자바스크립트는 처리할 메시지의 대기열을 사용한다. 각 메시지에는 이를 처리하기 위한 함수가 연결되어 있다.

Call Stack과 다르게 먼저 들어온 함수를 먼저 처리한다. (FIFO, First In First Out)

  1. 대기열에서 가장 오래된 메시지부터 큐에서 꺼내 처리하기 시작한다.
  2. 꺼낸 메시지를 매개변수로, 메시지에 연결된 함수를 호출한다.
  3. 호출로 인해 새로운 스택 프레임이 생성된다. 함수 처리는 스택이 빌 때까지 계속한다.
  4. 그 후, 큐에 메시지가 남아있으면 위의 처리를 반복하게 된다.

 

이벤트 루프 (Event Loop)

위에서 설명한 큐에서 일어나는 과정을 구현할 때 사용하는 구현 방식이다.

  • 모든 비동기 API들은 작업이 완료되면 콜백 함수를 태스크 큐에 추가한다.
  • 이벤트 루프는 현재 실행 중인 태스크가 없을 때 (콜 스택이 비었을 때), 태스크 큐의 첫 번째 태스크를 콜 스택으로 꺼내와서 실행한다.

 예)

queue.waitForMessage() 함수는 현재 실행중인 태스크가 없을 때 다음 태스크가 큐에 추가될 때까지 대기하는 역할을 한다.

while(queue.waitForMessage()){
  queue.processNextMessage();
}

 

실행 예시

function delay() {
    for (var i = 0; i < 100000; i++);
}
function foo() {
    delay();
    bar();
    console.log('foo!'); // (3)
}
function bar() {
    delay();
    console.log('bar!'); // (2)
}
function baz() {
    console.log('baz!'); // (4)
}

setTimeout(baz, 10); // (1)
foo();
  1. 콜 스택에 setTimeout 함수가 쌓이고, setTimeout함수는 브라우저에게 타이머 이벤트를 요청한 후에 바로 스택에서 제거되고, 10ms가 지나면 브라우저의 타이머가 baz 함수를 실행하지 않고 태스크 큐에 추가한다.
  2. 그 후에 foo 함수가 스택에 추가되고, foo 함수 내부에서 실행하는 함수들이 차례로 스택에 추가되었다가 실행 후 제거된다.
  3. 마지막으로 foo 함수가 실행을 마치면서 호출 스택이 비워지고 나면, 이벤트 루프는 태스크 큐에서 대기중인 callback함수 baz를 스택으로 추가하여 마지막으로 실행되게 된다.

위의 예시에서 baz 함수가 대기하고 있는 곳이 태스크 큐이고, foo 함수가 끝나자마자 실행될 수 있도록 해주는 것이 이벤트 루프의 역할이다.

 

⭐️ 총정리

자바스크립트 엔진이 싱글스레드 기반이기는 하지만, 자바스크립트가 구동되는 환경(브라우저, Node.js등)에서는 주로 여러 개의 스레드가 사용되며, 이러한 구동 환경과 자바스크립트 엔진이 상호 연동하기위해 사용하는 장치가 바로 이벤트 루프이다.

태스크 큐는 브라우저에서 제공하는 비동기 함수를 실행했을 때 발생한 콜백 함수들이 대기하는 큐 형태의 배열을 의미합니다.

 

코드가 실행되면서 자바스크립트 엔진의 콜 스택에 함수 호출이 쌓이고, 나중에 들어온 함수부터 차례대로 실행하게 됩니다.

이 때, setTimeout이나 DOM Events와 같이 브라우저에서 제공하는 비동기 함수들은 Web API를 호출하고 콜 스택에서 바로 제거됩니다. Web API는 함수를 실행하고 콜백 함수를 바로 실행하는 것이 아니라 태스크 큐에 전달받은 콜백 함수를 넣습니다

이벤트 루프는 현재 콜 스택에서 실행중인 태스크가 없으면, 태스크 큐의 첫 번째 태스크를 콜 스택으로 꺼내와 실행합니다. 그리고 이 과정을 태스크 큐가 빌 때까지 반복합니다.

 

참고 링크

 

이벤트 루프 - JavaScript | MDN

JavaScript의 런타임 모델은 코드의 실행, 이벤트의 수집과 처리, 큐에 대기 중인 하위 작업을 처리하는 이벤트 루프에 기반하고 있으며, C 또는 Java 등 다른 언어가 가진 모델과는 상당히 다릅니다.

developer.mozilla.org

https://meetup.nhncloud.com/posts/89

 

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

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

meetup.nhncloud.com

 

728x90
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함