V8 엔진은 어떻게 동작하는가?

Yeshin Lee
5 min readNov 13, 2022

--

JavaScript를 공부하다보면 V8에 대해 자연스럽게 접하게 되는데요. ‘구글에서 만든 오픈소스 JavaScript 엔진이다’, ‘C++로 쓰여졌다’, 정도로만 알고 있었는데 이번에 자세하게 알아보고자 합니다.

이름은 자동차의 8기통 피스톤 엔진에서 따왔다고 합니다. (The new JavaScript runtime was christened “V8”, a playful reference to the powerful engine you can find in a classic muscle car.)

V8은 2008년 8월 2일, 구글의 Lars Bak이 만든 JavaScript 및 WebAssembly 엔진입니다. (참고로, Chrome이 처음 만들어진 날이기도 합니다.) JavaScript 엔진으로는 최초의 JavaScript 엔진으로 Firefox에 내장되어 있는 SpiderMonkey나 Safari에 내장된 WebKit/JavaScriptCore, Microsoft Edge에 내장된 ChakraCore 등이 있는데요. 이는 JavaScript를 바이트 코드로 컴파일하는 JIT(Just-In-Time) 컴파일러로 구현할 수 있습니다. 다양한 엔진 사이에서 V8은 Node.js 런타임에 기본적으로 사용된다는 차이가 있습니다. 이 문제를 해결하고자 Node of WebKit인 NW.js Node.js 전용 ChakraCore(마지막 업데이트가 19년 12월이네요..)가 있습니다.

V8은 JavaScript 코드를 컴파일 및 실행하는 것외에 다음 기능을 제공합니다.

  • 콜 스택 핸들링
  • 객체에 할당된 힙 메모리 관리
  • 가비지 컬렉터: 사용하지 않은 메모리를 찾아 할당을 해제한다.
  • 데이터 타입, 연산자, 객체 및 함수 제공

V8은 총 4단계로 실행됩니다.

1. 호스트에서 환경 초기화

사실 이 과정은 V8이 아닌 브라우저에서 수행합니다. 브라우저는 호스트 환경(실행되는 환경, 브라우저입니다.)과 V8 엔진을 초기화합니다.

2. JavaScript 코드 컴파일

자체 parser를 사용해 JavaScript 코드는 AST(abstract syntax tree; 추상 구문 트리)로 변환됩니다.

3. 바이트코드 생성 및 해석, 실행

2017년까지는 3가지 파이프라인으로 구성되어 있었습니다.

  • full-codegen: 모든 코드를 기계어로 컴파일한다.
  • Crankshaft: 정통 자바스크립트 코드를 최적화하는 컴파일러
  • TurboFan: ES6 이후 최신 자바스크립트 코드를 최적화하는 컴파일러

(Crankshaft와 TurboFan은 둘 다 런타임 시점에서 동작합니다.)

이는 3가지 단점이 있었는데요.

  • 기계어의 특성상, 많은 양의 메모리를 필요로 한다.
  • 속도: 기계어는 실행할 때는 빠르지만 컴파일하는데에 시간이 소요되고, 바이트 코드는 컴파일하는데 상대적으로 짧은 시간을 요구하지만 실행 속도가 느립니다.(인터프리터는 바이트 코드를 실행하기 전에 해석하니까요.)
  • 두 최적화 컴파일러가 강하게 결합되어 있으면서 기계어의 복잡성으로 인한 유지보수가 어려웠습니다.

2017년 5.9버전의 V8은 인터프리팅으로 전환되었습니다. 현재의 V8은 AST에서 바이트 코드를 생성하는 Ignition 인터프리터와 TurboFan으로 이뤄진 파이프라인으로 구성되어 있습니다. 이는 Node.js 샘플 애플리케이션인 AcmeAir를 10% 이상 더 빠르게 실행하고 데스크톱 및 모바일 내의 V8 메모리 공간을 5 ~ 10%까지 줄인다고 합니다.

4. 일부 바이트코드 최적화

V8은 런타임 중 코드를 모니터링하면서 최적화합니다. 만약 실패한다면, 인터프리터는 기존 바이트 코드를 실행합니다.

V8은 객체를 관리하는데 Hidden class라는 방식을 사용한다고 합니다. 이 글을 읽었을 때 이해가 잘 가지 않아 넘겼는데, 다음 포스트에는 관련 내용을 적을 것 같습니다 :)

--

--