파이프라인, 단계별로
- 파싱 (SWC). 소스 파일은 Rust 네이티브 TypeScript 파서인 SWC로 파싱되므로, 대규모 프로젝트도 밀리초 단위로 파싱됩니다. 모듈 코드 생성, 변환 패스, 심볼 스캐닝은 여러 코어에서 병렬로 실행됩니다.
- 타입 해결. 컴파일러는 선언된 타입을 해결하고 나머지는 추론하여, 코드 생성이 시작되기 전에 모든 표현식에 구체적인 타입을 부여합니다.
- 타입화된 HIR와 모노모픽화. AST는 타입화된 고수준 IR(HIR)로 변환됩니다. 제네릭 함수와 클래스는 모노모픽화됩니다 —
Stack<number> 같은 각 인스턴스화는 구체적인 타입으로 개별 컴파일되므로, 제네릭은 런타임에 아무 비용도 들지 않습니다. 타입을 알 수 있는 경우, 메서드 호출은 정적 디스패치가 되고 객체 필드는 직접적인 고정 오프셋 로드가 됩니다. - 코드 생성 (LLVM). HIR은 LLVM IR로 변환되고 LLVM의 최적화 파이프라인 — 인라이닝, 루프 최적화, 벡터화 — 을 거친 뒤, 대상 플랫폼을 위한 머신 코드로 방출됩니다.
- 링크. 출력물은 평범한 플랫폼 실행 파일입니다: macOS의 Mach-O, Linux의 ELF, Windows의 PE — 그리고 모바일, 워치, TV, WebAssembly 타겟까지.
이 중 LLVM에 관한 부분 — 왜 Cranelift 대신 LLVM을 선택했는지, NaN-boxing이 동적 값을 어떻게 표현하는지, 옵티마이저가 타입화된 IR로 무엇을 하는지 — 은 별도의 심층 분석에서 다룹니다: LLVM 위의 TypeScript. NaN-boxing, 정적 디스패치, 제로 비용 추상화 같은 구현 세부 사항은 컴파일러 내부 구조에서 다룹니다.
동적 코드와 npm은 어떻게 되나요?
TypeScript는 내부적으로 여전히 JavaScript이며, 네이티브 TypeScript 컴파일러는 이 점에 솔직해야 합니다. Perry의 공식 test262 스위트 대비 적합성은 측정되고 공개됩니다 — v0.5.1146 기준으로 String 의미론은 79%, Array는 72%이며, 릴리스마다 계속 올라가고 있습니다. 순수 TypeScript/JavaScript npm 패키지는 perry.compilePackages를 통해 네이티브로 컴파일됩니다: axios, zod v4, express, fastify, hono는 오늘 바로 컴파일되어 실행됩니다. 완전한 엔진 의미론이 필요한 코드는 --enable-js-runtime으로 임베디드 V8 폴백을 선택할 수 있습니다.
자세한 이야기는 실제 npm 패키지와 적합성 스윕에 있습니다.
Perry는 다른 “네이티브 TypeScript” 시도들과 어떻게 다른가
Perry만이 TypeScript의 타입 애노테이션에서 컴파일 기회를 발견한 프로젝트는 아니지만 — 접근 방식은 크게 다릅니다. AssemblyScript는 엄격한 TypeScript 유사 언어를 오직 WebAssembly로만 컴파일합니다: 의도적으로 JavaScript와 호환되지 않으며, OS 실행 파일이나 네이티브 UI를 만들어내지 않습니다. Meta의 Static Hermes는 Hermes 엔진 안에서 타입화된 JavaScript 부분 집합을 사전 컴파일하며, 주로 React Native를 위한 것입니다 — 2026년 중반 기준으로 여전히 소스에서 빌드해야 하는 연구 프로젝트로 남아 있으며, 실제로 React Native에 배포된 Hermes V1 엔진에는 정적 컴파일 기능이 포함되어 있지 않습니다 (전체 비교).
Perry의 승부수는 두 축 모두에서 다릅니다: 입력 언어로는 표준 TypeScript를, 출력물로는 평범한 플랫폼 실행 파일 — CLI, 서버, GUI — 을 택했으며, 오늘 바로 Homebrew, APT, winget, 또는 npm으로 설치할 수 있습니다.
하나의 컴파일러, 10개의 타겟
코드 생성이 LLVM을 거치기 때문에, 하나의 코드베이스가 macOS, iOS, iPadOS, Android, Linux, Windows, watchOS, tvOS, WebAssembly, 그리고 순수 Web/JS로 컴파일됩니다 — Linux 머신에서 Windows, macOS, iOS 바이너리를 크로스 컴파일하는 것까지 포함해서요. GUI 앱은 실제 플랫폼 위젯(AppKit, UIKit, GTK4, Win32, JNI를 통한 Android) 위에 선언적 API를 제공하는 perry/ui를 사용합니다 — 웹뷰는 전혀 관여하지 않습니다.
다른 접근 방식과 비교하면 어떨까요: Perry vs Bun, Deno, Electron, Tauri, React Native, Static Hermes.