JavaScript V8 Engine

Hyunjun Jang·2022년 1월 16일
0

V8이란?

V8은 웹 브라우저를 만드는데 기반을 제공하는 구글에서 개발한 오픈소스 자바스크립트 엔진이다.

V8은 자바스크립트 코드를 실행 전에 최적화된 머신 코드로 컴파일하는 엔진이다.
(즉, V8은 자바스크립트 코드를 받아 컴파일하고 실행하는 C++ 프로그램이다.)
크롬 브라우저와 노드 js에서 사용된다.

V8의 등장배경

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

왜 머신 코드로 컴파일해야 할까?
V8 엔진이 어떻게 동작하는지 알아보기 전에, 애초에 왜 머신 코드로 컴파일하는지 간략히 짚고 넘어가자. 우리가 사용하는 컴퓨터 안에는 마이크로프로세서라는 작은 기계가 있는데, 이것은 CPU의 핵심 기능을 통합한 집적 회로(IC)다. 프로그래머가 어떤 코드를 짜서 컴퓨터에게 일을 시키려면 결국 이 마이크로프로세서가 해석할 수 있는 언어로 전달해야 한다.
마이크로프로세서는 이것을 만든 회사나 버전에 따라 각자 다른 언어를 사용하는데, 가장 많이 쓰이는 것들은 IA-32, x86-64, MIPS, ARM 등이다.
이 언어들은 하드웨어와 직접적으로 소통할 수 있는 코드들이고 그래서 기계어, 머신 코드라 불린다. 그러니까 결국 프로그래머들은 프로그래밍 효율을 위해 추상화 수준이 높은 high level 언어를 사용해서 코딩을 하지만 이는 결국 머신 코드로 컴파일되어야만 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 자료구조를 사용하여 컴파일 작업을 돕게 된다.

Refernce

https://v8.dev/blog/ignition-interpreter
https://www.freecodecamp.org/news/understanding-the-core-of-nodejs-the-powerful-chrome-v8-engine-79e7eb8af964/
https://hwan-shell.tistory.com/343
https://alledy.netlify.app/posts/v8-engine/

profile
Let's grow together😊

0개의 댓글