JS V8 Engine

양세희·2022년 5월 29일
0
post-thumbnail

V8이란?

V8은 웹 브라우저를 만드는데 기반을 제공하는 구글에서 개발한 오픈소스 자바스크립트 엔진이다. V8은 자바스크립트 코드를 실행 전에 최적화된 머신 코드로 컴파일하는 엔진이다. 즉, V8은 자바스크립트 코드를 받아 컴파일 하고 실행하는
C++ 프로그램인 것이다. 크롬 브라우저와 노드 js에서 V8이 사용된다.

V8의 등장배경

웹 브라우저 내부에서 자바스크립트의 속도 개선을 위해서 고안되었다.
자바스크립트 엔진은 웹 특성상 유저와 상호작용을 위해서 즉시성이 있는
인터프리터 방식을 사용하는데, 코드가 많아질수록 속도가 느려져서 구글맵 같은 기능을 구현하기에는 어려웠다. 따라서 V8은 속도 향상을 위해 자바스크립트 코드를 더 효율적인 머신코드로 번역한다.

왜 머신 코드로 컴파일 해야 할까?

V8 엔진이 어떻게 동작하는지 알아보기 전에,
애초에 왜 머신 코드로 컴파일 하는지 알아보자.

우리가 사용하는 컴퓨터 안에는 마이크로프로세서라는 작은 기계가 있는데,
이것은 CPU의 핵심 기능을 통합한 직접 회로(IC)다. 프로그래머가 어떤 코드를 짜서 컴퓨터에게 일을 시키려면 결국 이 마이크로프로세서가 해석할 수 있는 언어로 전달해야 한다.

마이크로프로세서는 이것을 만든 회사나 버전에 따라 각자 다른 언어를 사용하는데, 가장 많이 쓰이는 것들은 IA-32, x86-64, MIPS, ARM 등이다.

이 언어들은 하드웨어와 직접적으로 소통할 수 있는 코드들이고 그래서 기계어, 머신 코드라고 불린다. 결국 프로그래머들은 프로그래밍 효율을 위해 추상화 수준이 높은 고언어를 사용해서 코딩을 하지만 이는 결국 머신 코드로 컴파일 되어야만 CPU가 이해하고 처리할 수 있다는 것이다.

V8의 Compiler

V8은 JIT Compiler를 지원한다.
일반적인 Compiler에는 동적 컴파일(인터프리터)와 정적 컴파일(Compiler)가 있다. JIT Compiler는 이 두 개를 합친 것으로 실행 시점에서 인터프리터 방식으로 바이트 코드를 생성한다. 그 후 V8 Engine은 바이트 코드를 머신 코드로 만들고, 그 코드를 캐싱하여, 같은 함수가 여러 번 불릴 때 매법 머신 코드를 생성하는 비효율적인 일을 방지한다.

(인터프리터 방식은 한 줄을 읽고 실행하는 방식으로, 동일한 동작을 하는 함수가 여러번 나오더라도 이를 컴파일 하는 과정을 거치게 된다. 따라서 이는 매우 비효율적이며, JIT Compiler는 이를 방지하여 위와 같은 동작으로 실행되게 된다.)

V8 Engine에서 바이트코드로 바꾸는 컴파일러를 Ignition이라고 말한다. Ignition은 바이트코드를 생성하고 TurboFan이라는 컴파일러를 통해 최적화 컴파일 하는 과정을 거친다.

이렇게 빠르고 효율적인 컴파일러이기 때문에 JIT(Just-In-Time)이라고 불린다.

이를 통해 얻을 수 있는 이점이 있는데, 복잡한 최적화 과정은 바이트코드 컴파일러가 대신 해주므로 고려하지 않아도 된다는 장점이 있다.

바이트코드는 빠른 기계어 변환을 목적으로 설계되었기 때문에 일반적인 컴파일러보다 제작 과정이 수월하다.

V8 기능 정의

  • 자바스크립트 코드 컴파일 및 실행
  • 콜스택을 핸들링해서 자바스크립트 함수를 특정 순서에 따라 실행
  • 힙메모리 객체에 대한 메모리 할당 관리
  • 더 이상 사용하지 않는 객체를 관리 (가비지컬렉터)
  • 모든 데이터 타입, 연산자, 객체, 함수를 제공
  • 이벤트 루프를 제공 (이벤트 루프를 사용해서 Callback 함수들의 변화 감지)

JavaScript Engine AST

JavaScript는 인터프리터 되는 과정을 거치기 전에, 해당 소스들을 parser에서 Abstract Syntax Tree 형태로 바꾸게 된다.

parser는 구문 분석기로 해당 소스가 컴파일 되기 전에 parser로 소스를 공급해주면, 소스를 분석해서 구문 분석을 수행하고, 수행한 결과를 가지고 AST(추상 구문 트리)를 생성한다.

JavaScript의 parser는 lazy parser를 사용하는데, lazy parser의 궁극적인 목표는 중복되는 함수에 대한 처리와 만나는 함수를 사전에 구문 분석함으로써 함수를 건너뛸 수 있도록 하는 작업을 수행한다. 이러한 최적화 과정을 거친 후 컴파일러 알고리즘에서 많이 사용되는 AST 자료구조를 사용하여 컴파일 작업을 돕게 된다.

0개의 댓글