ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 자바스크립트 동작원리
    Programming/javascript 2021. 1. 22. 20:43

    자바스크립트 엔진

    자바스크립트 엔진에는 대표적으로 V8 엔진이 있습니다. V8 엔진은 c++로 제작되었으며 Node.js의 런타임으로도 사용됩니다. 아래는 엔진의 구조도를 간단히 나타낸 그림입니다.

     

    • Memory Heap : 메모리 할당이 일어나는 곳

    • Call Stack : 코드 실행에 따라 호출 스택이 쌓이는 곳

     

     

    런타임

    대부분의 자바스크립트 개발자들이 setTimeout과 같은 브라우저 내장 API를 사용합니다. 하지만, 이 API를 자바스크립트 엔진에서 제공하지는 않습니다.

     

    위 그림처럼, 자바스크립트 엔진 이외에도 자바스크립트에 관여하는 다른 요소들이 많습니다. DOM, Ajax, Timeout과 같이 브라우저에서 제공하는 API들을 Web API라고 합니다.

     

     

    Call Stack

    자바스크립트는 기존적으로 싱글 쓰레드 기반 언어입니다. 따라서 한 번에 한 작업만 처리할 수 있습니다. 

     

    Call Stack은 기본적으로 우리가 아는 프로그램 상에서 어디에 있는지를 기록하는 자료구조입니다. 함수 A를 실행하면 해당 함수는 스택에 들어가게 됩니다. 그리고 함수의 실행이 끝나면 해당 함수를 Call Stack에서 제거합니다.

     

    function add(x, y){
    	return x+y;
    }
    
    function printTwice(x){
    	var s = add(x, x);
    }
    
    printTwice(10);

    처음 엔진이 이 코드를 실행할 때는 Call Stack이 비어있습니다. 하지만 코드가 실행되면서 Call Stack은 아래와 같이 변합니다.

     

     

     

    Call Stack의 각 단계를 스택 프레임이라고 합니다. 

     

    이렇게 자바스크립트는 싱글 쓰레드 기반으로 하나의 작업이 오래 걸리게 된다면 브라우저는 이 외의 아무 작업도 못하게 됩니다. 그런데 자바스크립트는 어떻게 동시성을 가질까요?

     

     

    Callback Queue

    비동기적으로 실행된 콜백함수가 보관되는 영역입니다.

    예를 들어 setTimeout에서 타이머 완료 후 실행되는 함수 등이 보관됩니다.

     

    Event Loop

    Event Loop는 Call Stack과 Callback Queue의 상태를 체크하여,

    Call Stack이 빈 상태가 되면, Callback Queue의 첫번째 콜백을 Call Stack으로 밀어 넣습니다. 이러한 반복적인 행동을 틱(tick)이라고 부릅니다.

     

    정리하면,

    • V8 엔진에서 코드가 실행되면, Call Stack에 쌓인다.

    • 스택의 특성인 LIFO(Last in first Out)에 따라 제일 마지막에 들어온 함수가 실행되며 Stack에 쌓여진 모든 함수가 실행됩니다.

    • 비동기 함수가 실행된다면, Web API가 호출됩니다.

    • Web API는 비동기 함수의 콜백 함수를 Callback Queue에 밀어넣습니다.

    • Call Stack이 비게 된다면, Callback Queue에 있는 첫번째 콜백을 Call Stack으로 이동시킵니다.

    • 이러한 과정을 반복합니다.

     

    이러한 과정을 통해 자바스크립트는 싱글 쓰레드임에도 Web API, Event Loop, Callback Queue 덕분에 멀티 쓰레드인 것처럼 보입니다.

     

    예시를 들어볼까요?

    console.log('Hi');
    
    setTimeout(() => console.log('Hello'), 1000);
    
    console.log('bye');

    위 코드의 결과는 어떻게 될까요??

     

     

    Hi
    bye
    Hello

    결과는 이렇습니다. 이 과정을 그림으로 살펴볼까요?

     

     

     

    이처럼 setTimeout의 콜백 함수는 Call Stack이 비었을 때 Call Stack으로 불러와져 실행이 됩니다. 분명 쓰레드는 하나지만 한번에 여러가지의 일을 처리할 수 있는 것처럼 보여집니다.

     

     

    댓글

Designed by Tistory.