V8은 Google에서 개발한 오픈소스 자바스크립트 엔진으로, 주로 Chrome 브라우저와 Node.js에서 사용된다. V8은 자바스크립트 코드를 기계어로 변환하여 실행하는 고성능 엔진이며, 최신 웹 애플리케이션과 서버 애플리케이션의 핵심 역할을 담당하고 있다.
스크립트 언어와 현대 프로그래밍
프로그래밍 언어는 보통 작동 방식에 따라 컴파일 언어(Compiled Language)와 인터프리터 언어(Interpreter Language)로 구분되곤 한다. 초기 스크립트 언어는 주로 대형 컴퓨터 시스템에서 작업 자동화를 목적으로 사용되었지만, 현재는 뛰어난 범용성과 확장성을 바탕으로 복잡한 응용 프로그램 개발에도 효과적으로 사용되고 있다.
과거에는 스크립트 언어가 컴파일 언어에 비해 실행 속도가 느리다는 평가를 받았으나, 현대에는 AJITC와 같은 기술 덕분에 이 격차가 크게 줄어들었다. AJITC(Adaptive Just-In-Time Compilation)는 컴파일러와 인터프리터의 장점을 결합한 개념으로, 스크립트 언어의 실행 성능을 네이티브 컴파일 언어와 유사한 수준으로 끌어올렸다. 이러한 기술의 발전은 컴파일 언어와 인터프리터 언어 간의 구분이 점차 희미해지고 있음을 보여준다.
Chrome의 V8 엔진은 JIT 컴파일러를 기반으로 인터프리터와 컴파일러 방식을 결합하여 동작하는 대표적인 예이다. 이처럼 현대 자바스크립트 엔진은 빠른 실행 속도와 높은 효율성을 동시에 추구하며 진화하고 있다.
V8 엔진
자바스크립트 엔진은 자바스크립트 소스 코드를 기계어로 변환하여 실행하는 프로그램이다. 브라우저마다 각기 다른 엔진을 사용하지만, 기본적인 작동 원리는 유사하다. Google Chrome과 Node.js에서 사용되는 V8 엔진은 C++로 작성된 오픈소스 엔진으로, 높은 성능과 효율성을 자랑한다.
1. Parsing
자바스크립트 엔진은 소스 코드를 파싱하여 Abstract Syntax Tree를 생성한다. AST는 코드의 문법 구조를 계층적으로 표현한 데이터 구조로, 컴파일러가 이해할 수 있는 형태로 변환하기 위한 첫 단계이다.
2. Interpreter: Ignition
V8 엔진의 인터프리터는 Ignition으로, AST를 바탕으로 Bytecode를 생성하고 실행한다. Bytecode는 가상 머신에서 실행 가능한 중간 언어로, 플랫폼 독립성을 제공한다. Ignition은 코드 실행 초기 단계에서 빠르게 바이트코드를 생성하여 즉시 실행할 수 있도록 한다.
3. Optimizing Compiler: TurboFan
자바스크립트 코드 실행 중 프로파일링 데이터를 수집하여 뜨거운 코드(hot code)를 식별한다. 뜨거운 코드에 대해서는 아래 AJITC 부분에서 설명한다. 이러한 코드는 TurboFan이라는 최적화 컴파일러로 전달되어 고도로 최적화된 기계어로 변환된다. 최적화된 기계어는 반복 실행 시 성능을 크게 향상시킨다.
4. Deoptimization
만약 프로파일링 데이터가 변경되거나, 최적화된 코드가 예상치 못한 결과를 초래할 경우, 엔진은 최적화된 코드를 버리고 다시 Bytecode로 되돌린다. 이를 통해 실행 환경의 변화를 유연하게 처리한다.
AJITC (Adaptive Just-In-Time Compilation)
JIT 컴파일(Just-In-Time Compilation)은 프로그램을 실제 실행하는 시점에 기계어로 번역하는 컴파일 기법이다. V8은 AJITC를 통해 성능과 유연성을 극대화한다. 적응형 JIT 컴파일 방식으로, 모든 코드를 기계어로 변환하지 않고 자주 실행되는 코드만 선택적으로 최적화한다. 이를 통해 Compilation Overhead(컴파일 과부하)를 최소화하고 실행 성능을 개선한다.
다음은 예시 javascript 코드이다.
function sum(a, b) {
return a + b
}
for (let i = 0; i < 1000; i++) {
sum(1, 2)
}
위 함수는 반복적으로 호출되면서 뜨거운 코드로 간주된다. TurboFan은 이러한 코드를 최적화하여 실행 속도를 높인다. 하지만 동일 함수가 다른 데이터 타입과 함께 호출되면, 기존 최적화된 코드가 무효화되고 Deoptimization이 발생한다.
Reference
JavaScript Engines: The Good Parts - Benedikt Meurer, Mathias Bynens