[JS] JS엔진과 런타임 환경

Chanki Hong·2023년 1월 2일
0

JavaScript

목록 보기
20/30
post-thumbnail

JS 엔진

  • 대표적으로 Google V8 엔진. (Chrome과 Node.js에서 사용)
  • JS엔진은 Memory Heap과 단일 호출 스택(Call Stack)을 이용함. (JS가 싱글 스레드 기반, 콜백 큐인 이유)
  • JS를 동기적으로 작동시킴.

Memory Heap

  • 메모리 할당이 일어나는 곳.

호출 스택(Call Stack)

  • JS엔진의 호출 스택은 하나이며(싱글 쓰레드), 한 번에 한 작업(Task)만 처리 가능.
  • 코드 실행이 쌓이는 곳.
  • 기본적으로 프로그램 상에서 지금 어디에 위치하는지 기록하는 자료구조임.
  • 함수를 실행하면(실행 커서가 함수 안에 존재하면), 해당 함수는 호출 스택의 가장 상단에 추가(Push).
  • 함수가 끝날 때(리턴값을 반환할 때), 해당 함수는 호출 스택에서 제거(Pop) 됨.
  • 호출 스택은 후입선출; LIFO(Last In Fist Out).
function multiply(x, y) {
  return x * y;
}
function printSquare(x) {
  console.log(multiply(x, x));
}
printSquare(5);
  • 엔진이 위의 코드를 실행하는 시점에는 호출 스택이 비어있음.
  • 스택프레임(Stack Frame): 호출 스택의 각 단계를 나타냄.
  1. printSquare() 추가(Push).
  2. printSquare() 안에 있는 multiply() 추가.
  3. multiply() 가 값을 반환 하고 제거(Pop).
  4. 반환 값을 받아 console.log() 추가.
  5. console.log() 가 실행 되고 제거.
  6. printSquare() 가 실행이 끝나고 제거.

스택 오버플로우

  • 호출 스택이 최대 크기가 되면 스택 날리기(Blowing the stack) 발생.
// foo()가 반복 실행하는 재귀 함수.
function foo() {
  foo();
}
foo(); // RangeError: Maximum call stack size exceeded

단일 호출 스택의 문제

  • 단일 스레드는 멀티 스레드에서 일어나는 복잡한 문제가 일어나지 않는 장점이 있지만,
  • 제한적으로 실행한다는 문제가 있음.
  • 만약 브라우저 런타임 환경에서 복잡한 이미지 처리를 한다고 할때,
  • 이미지 처리 작업이 스택을 차지하고 있어 후속 작업을 처리할 수 없어짐. (blocking 발생)
  • 즉, 오랫동안 응답을 멈출 가능성이 있고,
  • 브라우저는 이 상황에서 오류 메세지를 표시함.
  • 단일 호출 스택의 문제를 비동기적 프로그래밍(Asynchronous Programming)으로 해결 가능.

런타임 환경(runtime environment)

  • 프로그래밍 언어가 구동되는 환경.
  • 런타임 환경에 따라 JS엔진을 포함한 다른 API 등이 제공.
  • JS가 브라우저에서 실행된다면 런타임 환경은 브라우저.
  • JS가 Node.js에서 실행된다면 런타임 환경은 Node.js.

브라우저에서 JS

  • JS엔진과 Web APIs(DOM, Ajax, setTimeout 등), Event Loop, Callback Queue가 관여함.
  • Node.js 환경에서는 다른 API가 제공됨. (라이브러리 등)
  • 특히 DOM 이벤트(click 등), http 요청, 콜백(callback)등 비동기적 실행은 동기 함수와 다른 과정으로 처리됨.

Web APIs(Web Application Programming interfaces)

  • DOM, Ajax, setTimeout 등의 비동기적 작업을 실행.
  • 브라우저가 공통적으로 제공하기로 규약한 API들이 많음. (MDN 보기)
  • 보안이슈로 인해 HTTPS에서만 사용가능한 API도 존재.
  1. 호출 스택(Call Stack)에 추가(push)된 비동기적 작업은 JS엔진이 아닌 Web APIs(C++로 구현)에 다시 추가(push).
  2. Web APIs는 비동기 작업을 수행하고, 콜백 큐(Callback Queue)로 코드 추가(push).

콜백 큐(Callback Queue)

  • 비동기적 작업이 실행된 이후 콜백함수가 보관되는 영역.
  • 호출 스택(call stack)과 다르게 선입선출; FIFO(Fist In Fist Out).
  • Task Queue, Microtask Queue, Animation Frames 3가지가 존재.
    • Task Queue: setTimeout, setInterval, setImmediate, I/O, UI 렌더링 등의 콜백 함수 저장.
    • Microtask Queue: ES6도입.Promise, Object.observe 등의 콜백 함수 저장.
    • Animation Frames: requestAnimationFrame 콜백 함수가 저장.
    • 이벤트 루프(Event Loop)에서 콜백 큐를 가져올 때 우선순위는 Microtask Queue > Animation Frames > Task Queue
    console.log('호출 스택');
     setTimeout(() => console.log('Task Queue'), 0);
     Promise.resolve().then(() => console.log('Microtask Queue'));
     /*
     호출 스택
     Microtask Queue
     Task Queue
     */

이벤트 루프(Event Loop)

  • 단일 호출 스택을 이용하는 JS엔진과 상호 연동하기 위한 장치.
  • 호출 스택과 콜백 큐를 감시함.
  1. 호출 스택(Call Stack)이 비어있을 때, 콜백 큐에 대기하고 있던 코드를 호출 스택으로 추가(push).
  2. 호출 스택에 쌓인 코드가 실행 되고 제거(Pop).

출처

0개의 댓글