티스토리 뷰

00. TL;DR

  • 바이트코드(Bytecode)는 자바스크립트 실행 시, 소스코드를 해석해 만든 중간 단계의 코드입니다.
  • 바이트코드는 CPU가 직접 실행하는 기계어는 아니지만, 인터프리터가 해석하고 실행할 수 있는 형식이며, JIT 컴파일의 기반이 되는 핵심 단위입니다.
  • 바이트코드는 빠른 초기 실행, 지연 컴파일, 함수 단위의 실행 컨텍스트 구성, 최적화 분석을 모두 고려한 구조로 자바스크립트 엔진의 핵심에 해당합니다.

01. 바이트코드란?

01.01. 정의

바이트코드(Bytecode)는 자바스크립트 코드가 실행되기 위해 먼저 변환되는 중간 코드(intermediate representation)입니다.

  • 자바스크립트 소스코드는 직접 실행되지 않고,
  • V8 엔진은 이를 먼저 바이트코드로 변환한 뒤,
  • 인터프리터(Ignition)가 바이트코드를 해석하며 실행합니다.
  • 바이트코드는 JIT 컴파일러(TurboFan)가 최적화 대상을 판단할 때 기준이 되는 자료이기도 합니다.
  • 바이트코드는 CPU 아키텍처에 독립적인 추상화된 명령어 집합입니다.

01.02. 주요 특징

특징 설명
✅ 중간 표현 소스코드와 기계어 사이 단계
✅ 실행 단위 인터프리터가 해석하여 실행
✅ 최적화 기반 JIT 컴파일러가 분석 후 최적화
✅ 함수 이름 보존 디버깅 및 최적화를 위해 이름 정보 포함
❌ 사람이 작성하지 않음 엔진 내부에서 자동 생성됨
❌ CPU가 직접 실행하지 않음 반드시 해석 또는 변환 필요
⚙️ 추상화됨 CPU 아키텍처에 종속되지 않음

02. 바이트코드의 생성과 실행

02.01. 실행 흐름

JS 코드
  ↓ (파싱)
AST(Abstract Syntax Tree)
  ↓ (인터프리팅)
바이트코드 생성
  ↓
인터프리터(Ignition)가 레지스터 기반으로 실행
  ↓
(Hot Code 감지)
  ↓
JIT 컴파일 → 최적화된 기계어 생성

02.02. 바이트코드는 "함수 단위"로 생성

  • 바이트코드는 파일 전체를 한 번에 생성하지 않고, 기본적으로 "함수 단위로 생성"됩니다.
  • V8은 지연 컴파일(Lazy Compilation) 전략을 사용하여, 함수가 실제로 호출되기 전까지는 바이트코드로 변환하지 않습니다.
  • 예외적으로, 전역 코드(Global Scope)는 파일 로딩 시 즉시 바이트코드로 변환됩니다.

02.03. 함수 단위 실행과 실행 컨텍스트

  • 자바스크립트는 함수가 호출될 때마다 별도의 실행 컨텍스트(Execution Context)를 생성하며, 이 컨텍스트 안에서 지역 변수, 파라미터, this, 스코프 정보 등이 관리됩니다.
  • 바이트코드 역시 이러한 컨텍스트 기반 실행에 맞춰 함수 단위로 독립된 바이트코드를 생성합니다.
  • 각각의 함수는 고유의 레지스터 공간, 스코프, 실행 흐름을 가지며, 해당 함수만의 바이트코드를 생성하고 실행함으로써 컨텍스트 기반 실행이 자연스럽게 지원됩니다.
  • 실행 컨텍스트와 함수 바이트코드는 1:1 대응하며, 메모리 및 최적화 관점에서도 매우 효율적인 구조입니다.

바이트코드가 함수 단위로 실행되는 이유는 자바스크립트가 실행 컨텍스트를 함수 단위로 분리하기 때문입니다.

02.04. 바이트코드에 함수 이름이 남아 있는 이유

V8에서 --print-bytecode 같은 디버그 옵션을 사용하면 다음과 같이 함수 이름이 바이트코드에 포함되어 나타납니다:

[generated bytecode for function: add]
Parameter count 3
Register count 4
000 S> 0x35 LdaNamedProperty a0, [1]
001     Star r1
...

이처럼 바이트코드와 함수는 긴밀하게 연결되어 있으며, 디버깅, 최적화 추적, JIT 대상 식별 등에 필수적인 정보를 제공합니다.

02.05. 예시

function add(a, b) {
  return a + b;
}
let y = add(2, 3);

→ 바이트코드 개념 출력 예 (단순화):

[generated bytecode for function: add]
LoadParam a
LoadParam b
Add
Return
  • add() 함수가 호출되기 전까지는 바이트코드가 존재하지 않음
  • 호출 시점에 컨텍스트가 생성되며, 그에 맞춰 바이트코드도 생성됨

03. 바이트코드 vs 기계어 vs 소스코드

구분 소스코드 바이트코드 기계어
사람이 작성
사람이 읽기 쉬움
CPU가 직접 실행
인터프리터가 실행
JIT 최적화 기반
플랫폼 독립성 (엔진 관점)
함수 이름 보존
실행 컨텍스트 단위 대응

04. 왜 바이트코드를 쓰는가?

  • 자바스크립트는 동적 언어이기 때문에, 소스코드를 바로 기계어로 컴파일하는 것이 어렵습니다.
  • 바이트코드는 실행 전에 소스코드를 분석하여 만든 간결한 중간 표현으로, 인터프리터가 빠르게 해석할 수 있습니다.
  • 바이트코드는 메모리 효율이 높고, 소스코드를 직접 해석하는 것보다 빠릅니다.
  • 함수 단위로 생성되므로, 실행 컨텍스트와 구조적으로 완전히 일치합니다.
  • 자주 호출되는 함수(Hot Function)는 JIT 컴파일러가 이를 분석하여 기계어로 최적화 컴파일합니다.
  • 최적화 기준, 실행 패턴, 인라인 캐싱 등의 분석도 바이트코드를 기반으로 이루어집니다.
  • 바이트코드는 함수 이름, 파라미터 수, 레지스터 수 같은 메타데이터도 함께 보존하여, JIT 및 디버깅에 유리합니다.

'FrontEnd > javascript' 카테고리의 다른 글

리터럴  (0) 2025.04.09
IEEE 754  (0) 2025.04.02
[JavaScript] 자바스크립트 생성자 함수  (0) 2025.03.26
[JavaScript] IIFE(Immediately Invoked Function Expression)  (0) 2025.03.23
[JavaScript] Shadow DOM  (0) 2025.03.21
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2026/04   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30
글 보관함