본문 바로가기
programming_kr/javascript

JavaScript - 콜스택, 태스크 큐, 이벤트 루프

by JSsunday 2022. 10. 1.
728x90

 

콜스택과 메모리 힙

자바스크립트는 단일 쓰레드로써 한 번에 한개의 작업을 진행합니다.

 

  • 메모리 힙(Memory Heap) : 정보를 저장하는 공간
  • 콜스택(Call Stack) : 실행 중인 코드를 추적하는 공간

자바스크립트는 힙, 큐와 함께 구성하는 단일 콜스택을 갖습니다. 메모리 힙은 자바스크립트 엔진이 구동되면서 변수, 함수 저장, 호출 등의 작업이 발생하는 공간입니다.

 

콜 스택(Call Stack)은 코드를 읽어내려가며 수행 할 작업들을 밑에서 부터 하나씩 쌓고, 메모리 힙(Memory Heap)에서 필요한 것들을 찾아서 작업을 수행하는 공간입니다. 콜 스택은 stack 자료구조를 가지고있으며 LIFO(Last In First Out) 또는 FILO(First In Last Out) 형태입니다.

 

간단한 예제입니다.

function first () {
  console.log("first");
}

function second () {
  first();
  console.log("second");
}

function third () {
  second();
  console.log("third");
}

third();

 

first
second
third

 

위의 코드가 실질적으로 콜 스택에 쌓이고 나가는 과정은 아래와 같습니다.

 

위 순서대로 쌓였다가 아래의 순서대로 빠져나간다고 생각하면 됩니다.

콜 스택은 자바스크립트 엔진에 위치하는 것이 아니라 실행환경인 브라우저에 위치합니다.

 

태스크 큐와 이벤트 루프

  • 태스크 큐(Task Queue) : 생성된 태스크가 적재되는 큐입니다. 태스크는 비동기 함수를 실행시켰을 때 콜스택에 바로 push 되지 않고 Web API(Window, Document, Event, XMLHttpRequest, Fetch 등)와 같은 백그라운드로 작업을 넘겨줍니다.

※ 태스크 큐는 엄밀히 말하면 태스크 큐와 마이크로 태스크 큐가 있습니다. 각각 사용하는 함수는 아래와 같습니다. 우선순위는 마이크로 태스크 큐 > 태스크 큐 입니다.

 

  • 콜백함수를 태스크 큐에 넣는 함수들
    • setTimeout, setInterval, setImmediate, requestAnimationFrame, I/O, UI 렌더링
  • 콜백함수를 마이크로태스크 큐에 넣는 함수들
    • process.nextTick, Promise, Object.observe, MutationObserver

 

setTimeout()을 실행하면 백그라운드로 넘기고 지정된 시간만큼 실행시킵니다. 그리고 그 안에 있는 콜백함수를 태스크 큐로 넘겨줍니다. 후에 콜스택이 모두 실행된 후에 태스크 큐에 있던 콜백 함수가 콜스택으로 push되어 실행됩니다.

여기서 태스크 큐에 있던 작업이 스스로 올라가는 것이 아니라 이벤트 루프(Event Loop)에 의해 올라갑니다. 이벤트 루프는 콜스택이 텅 빌 때 까지 기다리다가 빈 것을 확인하면 태스크 큐콜스택으로 올려줍니다. 그래서 콜스택에 쌓인 작업이 모두 끝나기 전에는 태스크 큐에 있던 작업들은 실행되지 않습니다.

 

콜스택태스크 큐, 이벤트 루프의 관계를 정리해봅시다

 

  1. 비어있는 태스크 큐에 1개의 태스크가 들어오고, 이벤트 루프에 의해 태스크가 큐에서 pop된다.
  2. pop된 태스크가 실행되면 자바스크립트 엔진에 의해 실행 가능한 코드범위로 실행 컨텍스트가 생성된다.
  3. 이벤트 루프태스크 큐에서 pop된 작업을 콜스택에 push한다.
  4. 콜스택에서 작업이 실행 되고, 콜스택에서 pop된다.
  5. 이벤트 루프태스크 큐에 작업이 있는지 확인한다.
  6. 이 과정을 반복한다.

 

콜스택에 쌓인 태스크들이 모두 실행이 되고, 종료가 된 시점에 태스크 큐에 쌓여있던 콜백함수(setTimeout())가 이벤트 루프에 의해 콜스택으로 push가 되어서 실행이 됩니다.

 

한가지 짚고 넘어가야 할 부분이 있습니다.

예를 들어, 콜스택에 1초가 걸리는 작업("test"를 1만번 출력하고 1초의 시간이 필요함)이 쌓여있다고 가정합니다. 그setTimeout(function(){ console.log('Hello')}, 0.5)을 실행하면 0.5초 후에 function의 결과("Hello")가 나와야합니다. 여기서 단순하게 추측을 해보면 당연히 "test"가 출력되다가 0.5초 후에 "Hello"가 나오고 나머지 "test"들이 나와야하지만 실제로는 "test"가 1만번 모두 출력이 된 후 "Hello"가 출력됩니다. 이유는 콜스택에 작업이 완료된 후에 이벤트 루프에 의해 태스크 큐에서 있는 작업이 콜스택으로 push되기 때문입니다. 따라서 콜스택에 작업이 완료되지 않은 이상 태스크 큐는 호출되지 않습니다.


참조
JavaScript - 콜스택, 태스크 큐, 이벤트 루프
728x90

'programming_kr > javascript' 카테고리의 다른 글

일급 함수란?  (0) 2021.01.01

댓글