javascript, typescript 시작하기

Created
July 16, 2025
Created by
D
DaEun Kim
Tags
typescriptjavascript
Property

자바스크립트는 원래 브라우저에서만 동작하는 것을 고려하여 만든 언어였다. 하지만 Node.js 의 등장으로 서버 측에서도 자바스크립트를 실행할 수 있게 되면서, 브라우저와 서버 모두에서 사용되는 범용 언어로 진화했다.

Node.js

  • 자바스크립트로 작성된 코드를 브라우저 외에 다른 환경에서 실행하기 위한 런타임
  • 컴파일을 담당하는 V8 엔진과 I/O 를 비동기 처리하는 libuv 포함

자바스크립트는 인터프리터 언어일까? 컴파일 언어일까?

자바스크립트를 실행하는 엔진의 동작방식에 따라 달라진다. 자바스크립트 엔진으로 가장 대표적인 V8 엔진은 인터프리터와 컴파일러의 특징을 혼합한 방식인 JIT(Just-In-Time) 컴파일을 수행한다. 아래 이미지는 Node.js 으로 자바스크립트 코드를 실행할 때 과정이다.

image

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은 추가된 콜백을 수행한다.

자바스크립트가 범용 언어로 빠르게 자리잡는 데 비해 타입 문법을 지원하지 않아서 생기는 문제들을 개선하고자 타입스크립트가 등장했다.

타입스크립트의 컴파일 과정

image
  1. 타입스크립트의 컴파일 과정에서도 AST 가 생성된다. (Typescript AST Viewer 참고)
  2. 생성된 AST 으로 타입 검사를 수행하고 타입 오류가 발견되면 컴파일은 종료된다.
  3. 타입 오류가 없을 경우 타입스크립트 컴파일러는 JS 코드를 생성한다.
  4. 타입스크립트 컴파일러가 생성한 JS 코드는 Node.js 으로 수행한다.