Created
July 16, 2025
Created by
D
DaEun KimTags
typescriptjavascript
Property
자바스크립트는 원래 브라우저에서만 동작하는 것을 고려하여 만든 언어였다. 하지만 Node.js 의 등장으로 서버 측에서도 자바스크립트를 실행할 수 있게 되면서, 브라우저와 서버 모두에서 사용되는 범용 언어로 진화했다.
Node.js
- 자바스크립트로 작성된 코드를 브라우저 외에 다른 환경에서 실행하기 위한 런타임
- 컴파일을 담당하는 V8 엔진과 I/O 를 비동기 처리하는 libuv 포함
자바스크립트는 인터프리터 언어일까? 컴파일 언어일까?
자바스크립트를 실행하는 엔진의 동작방식에 따라 달라진다. 자바스크립트 엔진으로 가장 대표적인 V8 엔진은 인터프리터와 컴파일러의 특징을 혼합한 방식인 JIT(Just-In-Time) 컴파일을 수행한다. 아래 이미지는 Node.js 으로 자바스크립트 코드를 실행할 때 과정이다.
1. AST 생성 (파싱 단계)
- V8의 파서는 자바스크립트 소스 코드를 읽고 토큰화한 후, 이를 AST로 변환한다.
- AST는 코드의 문법적 구조(예: 함수 선언, 변수, 연산자)를 계층적으로 나타낸다.
- 이 단계는 런타임 초기에 한 번만 수행되며, 이후 캐싱 가능하다.
2. 바이트코드 변환 및 인터프리터 실행
- AST는 Ignition 인터프리터로 전달되어 바이트코드로 변환된다.
- 바이트코드는 하드웨어로부터 독립적인 중간 표현으로, V8의 가상 머신 내에서 실행한다.
- Ignition 은 바이트코드를 한 줄씩 해석하며 초기 실행을 빠르게 처리한다.
- 이 과정은 런타임에서 동적으로 이루어진다.
3. 기계어로 Just-In-Time 변환 (선택적)
- 자주 실행되는 "핫 코드"는 TurboFan 컴파일러가 바이트코드를 분석하고 기계어로 변환하는 최적화 과정을 거친다.
- 기계어는 CPU가 직접 실행할 수 있는 네이티브 코드로, 하드웨어에 의존하지만 성능을 크게 향상시킨다.
- 이 변환은 런타임 중에 동적으로 발생하며, 코드 실행 패턴에 따라 최적화 된다. (예: 인라인 캐싱)
- 코드 수정 등의 사유로 최적화가 무효화되면 다시 바이트코드 변환 단계를 거친다.
libuv
- 컴파일 된 코드를 수행하는 과정에서 I/O 작업이 있으면 V8 엔진은 libuv 으로 작업을 위임한다.
- libuv 는 I/O 요청을 운영체제에 전달한다. 이 때 I/O 작업은 이벤트 큐와 이벤트 루프로 관리한다.
- I/O 작업이 완료되면 이벤트 큐에 콜백이 추가되고, V8은 추가된 콜백을 수행한다.
자바스크립트가 범용 언어로 빠르게 자리잡는 데 비해 타입 문법을 지원하지 않아서 생기는 문제들을 개선하고자 타입스크립트가 등장했다.
타입스크립트의 컴파일 과정
- 타입스크립트의 컴파일 과정에서도 AST 가 생성된다. (Typescript AST Viewer 참고)
- 생성된 AST 으로 타입 검사를 수행하고 타입 오류가 발견되면 컴파일은 종료된다.
- 타입 오류가 없을 경우 타입스크립트 컴파일러는 JS 코드를 생성한다.
- 타입스크립트 컴파일러가 생성한 JS 코드는 Node.js 으로 수행한다.