← 목록으로

Bun, TypeScript를 네이티브 코드로 선행 컴파일하는 AOT 컴파일러 실험 공개

요약
  • Bun이 TypeScript와 JavaScript를 네이티브 코드로 선행 컴파일하는 AOT 컴파일러 실험 결과를 공개했습니다.
  • 이 방식은 TypeScript의 타입 정보를 활용해 정적 검증과 코드 생성을 수행하며, 객체 모델의 안정성을 확보하고 프로토타입 변경을 제한하는 등의 특징을 가집니다.
  • 다만 타입 정보 활용 과정에서 기존 JavaScript와 일부 실행 의미가 달라질 수 있어 완전한 하위 호환성을 제공하지는 않습니다.
  • Bun이 TypeScript/JavaScript를 실행 전에 네이티브 코드로 컴파일하는 AOT(Ahead-of-Time) 컴파일러의 실험 결과를 공개함
  • 기존 bun build --compile은 JavaScript 번들과 Bun 런타임을 단일 실행 파일로 패키징하며, --bytecode는 JavaScriptCore의 바이트코드를 미리 생성하는 방식. 이번에 공개한 --compile --aot는 네이티브 코드 선행 컴파일을 지향하는 별도의 실험
  • TypeScript의 타입 정보를 컴파일 과정에서 활용해 정적 검증과 코드 생성에 반영하며, 컴파일 시점에 확인하기 어려운 값은 런타임에서 검증하는 방식
  • Bun 1.4의 기존 실행 방식과 실험적 AOT 컴파일러를 비교한 4부작 시리즈로, 각 예제의 실행 결과를 공개함

1. 타입을 활용한 컴파일과 실행 시점 검증

  • 컴파일 시점 검증: const port: number = "8080"처럼 정적으로 확인 가능한 타입 오류는 빌드 단계에서 거부하고 실행 파일을 생성하지 않음
  • 런타임 검증: JSON.parse()로 전달받은 객체가 선언된 인터페이스와 일치하는지 검사. number 필드에 문자열이 들어오면 TypeError 발생
  • 타입 단언의 의미 변경: 기존 TypeScript에서 컴파일 후 제거되는 as가 실제 형변환으로 동작. (raw as number) + 1에서 raw가 "5"라면 "51" 대신 6을 반환
  • Non-null assertion: x! 역시 런타임 검사로 동작하며, 값이 null 또는 undefined라면 오류 발생

2. 타입 안정성을 유지하는 객체 모델

  • any를 거쳐 전달된 객체라도 타입이 지정된 함수에 전달되면 실제 필드 타입을 검증
  • 이미 타입이 지정된 객체의 필드를 any로 우회해 다른 타입의 값으로 변경하려는 시도를 차단
  • 필수 필드를 delete로 제거할 수 없으며, number[] 배열에 문자열이 포함된 경우에도 오류 발생
  • 클래스 인스턴스에는 구조적 타이핑 대신 실제 클래스 정체성을 검사. 동일한 필드와 메서드를 가진 일반 객체를 클래스 인스턴스 대신 전달하면 거부

3. 프로토타입 변경 제한과 정적 컴파일

  • Object.prototype에 속성을 주입하거나 Array.prototype.map 같은 내장 메서드를 교체하는 행위를 차단
  • 사용자 정의 클래스의 프로토타입 메서드도 교체할 수 없도록 제한
  • 이러한 제약은 컴파일러가 객체 구조나 메서드 호출 대상을 안정적으로 가정할 수 있는 조건을 제공하며, AOT 최적화에 활용할 수 있음
  • 다만 모든 객체를 불변으로 만드는 것은 아니며, 일반 객체에 동적 속성을 추가하거나 Math.tau 같은 새 속성을 정의하는 JavaScript 동작은 여전히 지원

4. 네이티브 코드 생성과 JavaScript 호환성

  • AOT로 컴파일된 함수에 toString()을 호출하면 기존 JavaScript 소스 대신 [native code]가 표시됨
  • 기존 JavaScript의 Object.keys(), 동적 속성 추가, 올바른 타입의 JSON 파싱 등은 동일하게 동작
  • 타입 정보를 컴파일에 활용하는 과정에서 기존 TypeScript/JavaScript의 일부 실행 의미가 변경되므로 완전한 하위 호환성을 제공하는 방식은 아님
그냥 목록으로
원문 보기 ↗