JavaScript는 CallStack, EventQueue 이용하여 Single Thread 기반으로 비동기적으로 동작한다. Single Thread 기반에서는 단 하나의 CallStack만 존재하기 때문에 네트워크 요청 등 비용이 많이 드는 연산을 수행하게 되면 매우 비효율적으로 동작된다. 이러한 문제점을 어떻게 해결하는지 하나씩 확인해보자.

Javascript Engine

위 그림같이, JavaScript Engine은 주요하게 두 가지 구성 요소를 가지고 있다.

Runtime

JavaScript는 단일 스레드 기반이기 때문에 호출 스택이 하나만 존재한다. 동기적인 관점으로 바라보면 동시에 여러개의 태스크를 실행할 수 없다. 이러한 단점을 해결하기 위해, 프로그램은 자바스크립트 엔진이 아닌 Web API(DOM, AJAX, TIMEOUT, 비동기 함수 지원) 이용하여 비동기적으로 동작할 수 있게 된다. 예로 들어 보면 아래와 같다.

위와 같은 일련의 과정을 통해, JavaSrcipt는 처리 비용이 큰 작업을 Web API 이용하여 비동기적으로 해결한다고 볼 수 있다. 따라서 단일 스레드 단점을 극복할 수 있는 것이다.

Call Stack

스택은 FILO(선입 후출) 자료구조로 함수 호출 단위를 스택 프레임에 쌓아가고, 각각은 호출 함수에 대한 복귀 주소를 기억하고 있다. 여러 언어로 개발을 해보며 Stack Trace 볼 수 있었을 것이다. 예외가 발생한 스택 프레임부터 복귀 주소로 회귀하며 Stack Tracing 하는 것은 스택 프레임 구조이기에 가능한 것이다.

Event Queue

setTimeout() 함수에 지연시간을 0 으로 주는 예를 보자.

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

function b() {
    a(); // a
    
    setTimeout(function() {
        console.log('b'); // b
    }, 1000);
    
    c(); // c
}

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

b();