[ASAC 7기] 자바스크립트 런타임 환경: 브라우저와 서버에서의 실행 메커니즘 정리

민준·2024년 12월 18일
0

1. 자바스크립트 런타임 환경

자바스크립트 엔진은 웹 브라우저, 웹 서버에서도 실행되며, 이를 가능하게 만드는 것이 자바스크립트 런타임 환경

1.1. 자바스크립트 런타임 = 자바스크립트 엔진 + API 및 라이브러리

자바스크립트 엔진은 언어의 문법만을 처리하며, 다양한 API와 라이브러리 덕분에 다양한 기능을 제공

  • 웹 브라우저 (예, 우리가 사용하는 Chrome) = V8 자바스크립트 엔진(싱글쓰레드) + Web APIs(멀티쓰레드)
    • Web APIs = 웹 브라우저에서 제공하는 API(예: Canvas API, Cookie API, File System API 등)
  • 웹 서버 (예, 서버로 많이 사용하는 Node.js) = V8 자바스크립트 엔진 + Node APIs + LIBUV
    • Node APIs = Node.js에서 제공하는 API(예: 파일 시스템 접근, 네트워크 요청 등)
    • LIBUV = Node.js에서 비동기 I/O를 처리하기 위한 핵심 라이브러리(멀티 스레드 지원)

자바스크립트 엔진 기반의 자바스크립트 런타임의 종류는 점차 많아지고 있다.

  • 웹 서버를 위한 Deno.js (Node.js 창시자가 만든 새 자바스크립트 런타임, 에너그램, V8엔진을 사용한다.)

  • 웹 서버를 위한 Bun.js (크롬 V8 엔진이 아닌 사파리 JSC 엔진 기반)

    • JRE(Java Runtime Environment) = JVM(Java Engine) + 라이브러리(Collection 등 유틸)

구성 1 : 자바스크립트 엔진 구성 (V8 엔진 기반으로 설명)

V8 자바스크립트 엔진은 웹 브라우저 크롬에서도 사용되고, 웹 서버 Node.js 에서도 사용되는 유명한 엔진

  • (1) 싱글스레드 : 모든 자바스크립트 코드(문법) 실행은 단 하나의 스레드가 실행한다.
  • (2) 메모리 = Stack + Heap 두 개만 기억
    • 메모리 영역은 정말 간단히 추상화해서 이해하자면 Heap 과 Stack 으로 구성되어있다
      • Heap : 선언 및 할당된 객체, 변수 및 함수 저장 (바구니) → 한마디로 객체 저장소
      • (Call) Stack : 함수 실행 순서대로 적재 및 수행
        • Stack : 함수 호출을 위한 영역으로 파라미터나 함수 내 지역 파라미터 저장

구성 2 : API 및 라이브러리

  • 자바스크립트 엔진만으로는 브라우저나 서버의 기능을 사용할 수 없기 때문에, 이를 가능하게 만드는 API들이 존재합니다.

    자바스크립트에서 제공되는 문법을 제공한 모든것들은 런타임 환경 내 API 가 제공하는것이라 생각하면된다

  • Web APIs = 웹 브라우저에서 제공되는 다양한 API 들

    • Canvas API : 웹 브라우저에 2D, 3D 그림을 그리기 위한 툴 - 웹 브라우저로 그림판 만들기 가능
    • Cookie API : 웹 브라우저 내 Cookie 조회 및 조작 기능을 제공
    • File System API : 윈도우나 맥북에 저장되어있는 디렉토리와 파일에 접근 (조회나 저장)
    • Keyboard API : 어떤 키 치고있는지 인지하고 그에 알맞은 이벤트 수행 - 복사붙여넣기 방지 기능
  • Node APIs = 웹 서버에서 제공되는 다양한 API 들 (단일 웹 서버이기에 API 모두 지원)

브라우저는 DOM 조작과 UI 관련 작업에 최적화된 API 제공(Web APIs), Node.js는 파일 시스템 접근 및 네트워크 처리에 최적화.

  • 다양한 웹 브라우저가 존재하기에 Web APIs 는 몇몇의 웹 브라우저에서는 어떤 API 는 제공되지 않는다.
  • 이로인해 각각의 브라우저마다 호환성 체크를 해야한다.

2. 자바스크립트 런타임 환경 종류

자바스크립트는 다양한 환경에서 실행될 수 있으며, 각 환경에 맞는 런타임이 존재합니다.

2.1. 웹 브라우저 : Chrome (V8 자바스크립트 엔진)

자바스크립트 엔진 + Web APIs

  • 자바스크립트 엔진 : 싱글스레드 + 메모리(Stack + Heap)
  • Web APIs : Web Worker API 통해 멀티스레드가 제공되며 자바스크립트 동작 중 비동기가 필요한 상황
    • 비동기 처리 (병렬 처리) : 비동기 처리엔 2개가 필요하다 = 메인 함수 + 콜백 함수 (비동기 완료 시 호출)
  • Task Queue : (비동기 완료 시 호출) 콜백 함수 적재 및 대기
  • Event Loop : 자바스크립트 엔진 메모리 중 Stack 내 콜백 함수 적재 후 실행

순서

  • JS 엔진 → 메인(떡썰기) / 웹 API → 멀티쓰레드(글쓰기)
  • JS엔진이 큐에서 콜백함수를 호출함(부르기 전까지 큐에서 대기)
  • 이때 호출을 도와주는것이 이벤트 루프
  • 하지만 스택(콜스택)에서 일처리가 많으면 우선순위가 스택에 있는것이 먼저 처리가 된다.

2.1.1. Web Worker API 직접 사용 시 비동기 로직 구현 가능

프론트엔드 개발자가 직접 자바스크립트로 멀티스레드를 활용하여 웹 브라우저 기능을 개발하고 싶을 시

  • Web APIs 종류

    • Web Worker API 브라우저에서 멀티스레드를 사용할수 있게 해주는 API

      Web Worker는 별도의 스레드에서 실행되는 JavaScript 코드로, 주 스레드(메인 스레드)와는 독립적으로 동작합니다. 하지만 두 스레드 간의 데이터 전달이 필요할 때, postMessage와 onmessage를 사용하여 메시지를 주고받을 수 있습니다.

      postMessage와 onmessage
      postMessage: 한 스레드에서 다른 스레드로 메시지를 보낼 때 사용하는 메서드입니다.
      onmessage: 메시지를 받을 준비가 되어있는 스레드에서 해당 메시지를 처리하는 이벤트 리스너입니다.

    • Dedicated Web Worker : 특정 웹 페이지만 적용되는 워커

    • Shared Web Worker : 여러 웹 페이지에서 공유 가능한 워커

    • Service Worker API : 오프라인 지원, 푸시 알림, 백그라운드 동기화 등 특수 기능을 수행하는 워커, 웹 브라우저(웹앱)와 인터넷 사이의 Middleware 혹은 Proxy 동작

      • PWA : 오프라인 수행도 가능하여 웹앱이 앱과 유사하게 동작되게 점진적(Progressive)으로 향상
        • 웹 푸시 알림 서비스
        • 백그라운드 동기화 기능
        • 네트워크 인터셉트(헤더, 요청, 응답 조작 등) 및 캐싱
      • 웹 페이지가 닫히더라도 비활성화되지 않아 브라우저 창이 닫히더라도 푸시 알림을 받을 수 있다.

        연결이 해제가 되어도 웹페이지가 돌아간다. 이유는 캐싱이 되어있기 때문이다.

  • (심화) 동작 : postMessage, onmessage 와 같이 Pub/Sub Pattern 으로 구현

    Pub/Sub Pattern (퍼블리셔/서브스크라이버 패턴)
    Pub/Sub Pattern은 메시지를 주고받는 디자인 패턴입니다. 퍼블리셔(발행자)가 메시지를 보내면, 이를 구독하고 있는 서브스크라이버(구독자)가 메시지를 받는 구조입니다.
    postMessage는 퍼블리셔 역할을 하고, onmessage는 서브스크라이버 역할을 하여 메시지를 받는 구조로 동작합니다.

    • 스레드간 데이터 통신을 위해 MessageChannel 활용 (onmessage + postMessage)

      MessageChannel은 두 개의 메시지 포트를 제공
      이 포트를 통해 두 스레드 간에 데이터를 비동기적으로 주고받을 수 있다.
      이 방식은 postMessage와 onmessage를 사용한 기본적인 메시지 전달 방법을 보강하는 더 고급 기능입니다.

  • CPU 코어 수만큼 Web Worker 생성하기
    멀티스레드를 활용할 때, 스레드의 수는 CPU의 코어 수에 맞추는 것이 좋다.
    Web Worker의 수를 CPU 코어에 맞추는 이유는 각 스레드가 물리적 또는 논리적 코어에서 실행되기 때문.
    그러나, 브라우저나 Node.js에서 코어 초과 워커를 생성해도 스케줄링에 의해 적절히 관리되므로 성능 저하가 반드시 발생하지는 않음.

2.2. 웹 서버 : Node.js (V8 자바스크립트 엔진)

자바스크립트 엔진 + Node APIs + LIBUV

  • 자바스크립트 엔진 : 싱글스레드 + 메모리(Stack + Heap)
  • Node APIs : 조금 놀라운 사실은 Node.js 는 C/C++ 언어를 통해 만들어졌다 (그러니 LIBUV 사용했겠지 → LIBUV는 대체불가)
    • Node-API 약자로 N-API 를 사용하며 구현체는 C/C++ 뿐만 아니라 Rust 언어도 사용 가능하다.
  • LIBUV : Blocking 혹은 Non-blocking 비동기 처리(네트워크, 파일 I/O 등)를 위해 스레드와 커널 제공
    • Event Queue : 모든 요청이 적재 및 대기
    • Event Loop : 싱글스레드가 하나씩 처리하여 비동기 처리는 아래에 위임, 응답은 Node APIs 로 전달
      • Worker Thread : 처리 중 Blocking 비동기 처리가 필요한 경우
      • OS(Kernel) 내 비동기 인터페이스 : 처리 중 Non-Blocking 비동기 처리가 필요한 경우

0개의 댓글