[F-Lab 모각코 챌린지 58일차] JavaScript Engine

Nami·2023년 7월 28일
0

66일 포스팅 챌린지

목록 보기
58/66

JavaScript Engine

JavaScript 코드를 실행하는 프로그램 또는 인터프리터

  • 웹 브라우저, 서버 사이드 환경, 모바일 앱 등에서 자바스크립트 코드를 실행하여 동적인 웹 페이지나 애플리케이션을 구현하는 데 사용된다.

자바스크립트 엔진의 대표적인 예는 Google V8 엔진이다. V8은 Chrome과 Node.js에서 사용한다.

ECMAScript (ES6)

ECMAScript(이크마스크립트)는 자바스크립트(JavaScript)의 표준 규격을 정의하는 스크립트 언어 표준.

  • js엔진이 하나가 아니라 여러 개이고 브라우저 별로 다르기 때문에 표준이 없다면 일관되지 못해 큰 문제가 될 수 있다.
  • javascript를 표준화하여 여러 엔진과 브라우저에서 일관된 동작을 보장하고 개선하기 위해 만들어졌다.
  • ECMA 국제 표준화 기구에 의해 관리된다.
  • ES5: 2009년에 출시, 대부분의 웹 브라우저가 지원하는 가장 오래된 버전. strict mode(엄격 모드), JSON 객체, 배열 메서드 등이 도입
  • ES6: 2015년에 출시된 버전. 대규모 업데이트를 수행. 화살표 함수, 클래스, 모듈, 프로미스 등 많은 새로운 기능과 문법이 도입

엔진의 주요 두 구성요소는 메모리 힙과 호출 스택이다.

Memory Heap 메모리 힙

  • 참조 타입(객체, 배열, 함수 등)이 저장된다.
  • Heap은 동적으로 데이터를 할당할 수 있는 메모리 영역이다.
  • 크기를 예측하기 힘든 참조 타입을 저장하기에 적합한 구조.

Call Stack 호출 스택

Js는 기본적으로 Single Thread 기반 언어이다. 호출 스택이 하나라는 소리이다.
따라서 한 번에 한 작업만 처리할 수 있다.

  • 원시 타입 값실행 컨텍스트가 저장된다.
  • 우리가 프로그램 상에서 어디에 있는지를 기록하는 자료구조
  • JavaScript 코드가 실행되며 생성되는 실행 컨텍스트(Exeution Context)를 저장하는 자료구조
  • 함수가 호출되면 해당 함수의 실행 컨텍스트가 콜 스택에 순차적으로 쌓이고, 함수가 종료되면 스택에서 해당 실행 컨텍스트가 제거된다.
  • 컴퓨터 프로그램에서 현재 실행 중인 서브루틴에 관한 정보를 저장하는 스택 자료구조.
  • 프로그램에서 함수 호출을 관리하는 데이터 구조
  • FILO First In Last Out 구조

함수에 들어가면 스택 맨 위에 PUSH. 함수에서 반환하면 스택의 맨 위에서 POP된다. 이것이 스택이 할 수 있는 전부이다.

function multiply(x, y) {
    return x * y;
}
function printSquare(x) {
    var s = multiply(x, x);
    console.log(s);
}
printSquare(5);

처음 엔진이 이 코드를 실행하는 시점엔 호출 스택이 비어있지만 코드가 실행되면서 호출 스택은 아래와 같이 변한다.

호출 스택의 각 단계를 스택 프레임(Stack Frame)이라고 한다.

  • 스택 프레임은 함수가 호출될 때마다 스택에 추가되며, 함수의 매개변수, 지역 변수, 반환 주소 등의 정보를 포함한다.
  • 호출된 함수의 실행이 끝나면 해당 함수의 스택 프레임이 스택에서 제거되고, 이전에 호출한 함수로 돌아가는 것.

예외(Exception)가 발생했을 때, 콘솔 로그 상에서 나타나는 스택 트레이스(Stack Trace) 는 해당 예외가 발생한 지점에서부터 예외가 처리될 때까지의 호출 스택의 상태를 보여주는 것이다.

  • 스택 트레이스는 호출 스택의 각 단계에 있는 함수들의 정보를 보여주는 것.
  • 개발자는 예외가 발생한 원인을 파악하고 디버깅하는 데 도움을 받을 수 있다.
function foo() {
    throw new Error('SessionStack will help you resolve crashes :)');
}
function bar() {
    foo();
}
function start() {
    bar();
}
start();


"Blowing the stack" — 최대 호출 스택 크기에 도달했을 때 발생한다. 특히 재귀 반복문 코드를 광범위하게 테스트하지 않고 실행했을 때 자주 발생한다.

function foo() {
    foo();
}
foo();

특정 시점에 함수 호출 횟수가 호출 스택(Call Stack)의 최대 허용치를 넘게 되면 브라우저가 이런 에러를 발생시킨다.

The Runtime 런타임

컴퓨터 프로그램이 실행되는 동안에 실제로 동작하는 환경을 의미.

컴퓨터 언어로 작성된 프로그램은 실행되기 전에 기계어로 변환되어야 하며, 이 변환은 컴파일러나 인터프리터에 의해 수행된다. 런타임은 이러한 변환 이후 프로그램이 동작하는 동안의 환경과 동작을 관리한다.

Concurrency 동시성 & the Event Loop 이벤트 루프

자바스크립트 엔진은 한 번에 단 한 가지의 일만 수행 가능한 싱글 스레드(Single thread) 방식으로 동작한다는 것은 알겠다! 그렇다면 setTimeout과 같은 비동기 함수들은 어떻게 논블로킹 방식으로 처리되는 걸까? 이 또한 프로그램이 멈추게 하는 요소였을텐데 말이다.

이런 자바스크립트 엔진에 동시성(Concurrency)을 지원하기 위해 웹 브라우저는 이벤트 루프(Event Loop)라는 것을 지원한다.
비동기 작업을 위해 사용했던 setTimeoutsetInterval 함수는 ECMA Script의 기본 사양이 아닌 웹 브라우저에서 별도로 제공하는 Web API이다.
물론 기본적으로 소스 평가 과정을 거쳐 실행 컨텍스트로 올라가는 것은 동일하지만, 비동기 동작을 위한 타이머 정보(호출 시간, 콜백 함수)는 웹 브라우저나 Node.js와 같은 자바스크립트 런타임 환경에 의해 관리됨.

const foo = () => console.log("First");
const bar = () => setTimeout(() => console.log("Second"), 500);
const baz = () => console.log("Third");

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

// First
// Third 
// Second

  1. bar 함수 호출, bar함수는 setTimeout 함수를 반환한다.
  2. setTimeout에 전달한 콜백은 Web API에 추가되고, setTimeout 함수와 bar는 호출 스택에서 제거됨.
  3. 타이머가 실행되는 동안, foo가 호출되고 "First"log한다. foo(undefined)를 반환하고, baz가 호출되며 콜백이 Queue에 추가된다.
  4. baz"Third"log한다. 이벤트 루프는 baz가 반환된 후 호출 스택이 비어있다고 판단하여 콜백을 Call stack에 추가한다.
  5. 콜백은 "Second"log한다.

이벤트 루프는 대기 중인 모든 콜백을 실행한다. 대기 중인 콜백들은 마이크로 태스크(Micro-tasks)와 매크로 태스크(Macro-tasks)로 큐에 분류된다.






  • 태스크 큐: 비동기 처리를 위해 등록된 콜백 함수들이 잠시 대기하는 공간
  • 마이크로 태스크 큐: 프로미스의 후속 처리를 위해 등록된 콜백 함수들이 잠시 대기하는 공간
  • 이벤트 루프: 호출 스택이 비어있을 때, 태스크 큐에 등록된 콜백 함수를 콜 스택에 옮기는 작업을 수행

이벤트 루프는 호출 스택(Call Stack)과 태스크 큐를 계속 지켜 보면서, 호출 스택이 비어있을 때 태스크 큐에 등록된 콜백 함수들을 호출 스택에 순차적으로 옮긴다. 만약 마이크로 태스크 큐에 콜백 함수가 있다면, 태스크 큐보다 우선적으로 참조한다.

이처럼 태스크 큐와 이벤트 루프를 갖고 있는 웹 브라우저와 자바스크립트 엔진의 협업에 의해 우리는 자바스크립트에서도 비동기 함수를 사용할 수 있는 것!!

실행 컨텍스트에 대해 좀더 깊게 공부 해보겠다.


0개의 댓글