컴퓨터는 본래 0과 1밖에 이해하지 못하기 때문에, 각종 프로그래밍 언어로 작성된 코드는 실행에 앞서 컴퓨터 언어(machine code)로 변환되는 과정을 거쳐야 한다.
이 때 프로그래밍 언어별로 machine code로 변환되는 방법이 다른데, 이 방법에 따라 언어를 컴파일러(compiler) 언어, 인터프리터(interpreter)언어로 나누기도 한다.
이 둘의 특징을 비교하면 다음과 같다.
| 컴파일러 언어 | 인터프리터 언어 |
|---|---|
| 코드가 실행되기 전 단계인 컴파일 타임에 소스 코드 전체를 한번에 머신코드로 변환한 후 실행한다 | 코드가 실행되는 단계인 런타임에 문(line)단위로 한 줄 씩 중간 코드인 바이트코드로 변환한 후 실행한다 |
| 바이너리(binary) 실행파일을 생성한다 | 실행 파일을 생성하지 않는다 |
| 컴파일 단계와 실행 단계가 분리되어 있다. 명시적인 컴파일 단계를 거치고, 명시적으로 실행 파일을 실행한다 | 인터프리트 단계와 실행 단계가 분리되어있지 않다. |
| 인터프리터는 한 줄씩 바이트코드로 변환하고 즉시 실행한다 | |
| 컴파일과 실행단계가 분리되어 있으므로 코드 실행 속도가 빠르다 | 인터프리트 단계와 실행 단계가 분리되어 있지 않고 반복 수행되므로 코드 실행 속도가 느리다 |
자바스크립트는 본래 순수 인터프리터 언어였다.
그러나 모던 자바스크립트 문법과 자바스크립트를 기반으로한 복잡한 프레임워크가 등장하면서, 느린 실행 속도를 가진 순수 인터프리트 방식에서 벗어날 필요가 있었다.
그래서 구글의 V8엔진을 비롯해 대부분의 현대 자바스크립트 엔진은 인터프리터 방식과 컴파일러 방식을 혼합한 JIT(JUST-IN-TIME) 방식을 사용한다.

파싱 과정에서 각 코드라인을 const, function 키워드 등 자바스크립트 언어적으로 유의미한 단위의 조각들로 쪼개서 AST(Abstract Syntax Tree)라는 데이터 구조로 저장한다.
이 과정에서 문법적 오류가 있는지 점검하고, AST는 이후 machine code 생성에 사용된다
<AST 구조 예>

AST를 machine code로 컴파일하는데, 이 때 코드의 빠른 실행을 위해 코드 최적화를 최소한으로 한다.
이후 별도의 파일 생성 없이, 실행단계에서 컴파일된 machine code를 바로 실행하게 된다.
메인 스레드에서 파싱이 완료된 machine code가 실행된다.
이 때, 메인 스레드와 분리된 별도의 스레드에서 코드에 대한 최적화 & 재컴파일을 진행하며 기존 코드를 대체하는 과정을 반복한다 → 코드 실행과 컴파일이 동시에 이뤄지게 된다
JIT(Just-In-Time) compilation은 컴파일 방식처럼 분리된 컴파일 단계와 실행 단계를 가지지만, 초기 컴파일 단계에서의 코드 최적화를 최소한으로 하고 별도의 파일 생성 없이 machine code를 바로 실행한다.
이후 실행 단계에서 메인 스레드와 분리된 별도의 스레드에서 코드에 대한 최적화 & 재컴파일을 하며, 기존 코드를 최적화된 코드로 대체하는 작업을 반복한다. 즉, 인터프리터 방식처럼 실행단계에서 코드를 재컴파일해가며 실행한다.