큰 TS 프로젝트에서 tsc --noEmit을 돌리면 체감상 느리다는 이야기가 꽤 오래 나왔습니다. VSCode 팀이 자기네 코드베이스를 기준으로 공개한 수치를 보면 체감이 아니라 실측입니다. TypeScript 6.0 기준 전체 타입 체크에 125.7초가 걸리던 작업이 TypeScript 7.0에서는 10.6초로 줄었습니다. 컴파일러 자체를 JavaScript에서 Go로 다시 작성했기 때문입니다.

TypeScript 공식 로고 — 파란 사각형 안에 TS 글자
이미지: microsoft/TypeScript-Website 공식 저장소의 브랜드 로고

여기까지 온 과정

Go 포트는 처음부터 tsc라는 이름으로 나오지 않았습니다. 2025년 5월에 @typescript/native-preview라는 별도 패키지로 먼저 나왔고, 이때는 명령어도 tsgo였습니다. 기존 tsc와 나란히 써보라는 의도였습니다.

npm install @typescript/native-preview
npx tsgo # tsc 쓰듯 그대로 쓰면 됩니다

이 프리뷰가 RC를 거쳐 2026년 7월 8일 TypeScript 7.0으로 정식 출시되면서 명령어 이름도 다시 tsc로 돌아왔습니다. 지금은 평소 쓰던 설치 명령 그대로 네이티브 바이너리가 들어옵니다.

npm install -D typescript
npx tsc --version
# Version 7.0.2

실제로 설치해서 node_modules/typescript를 열어보면 구조가 바뀐 게 보입니다. lib/tsc.js는 이제 컴파일러 본체가 아니라 실행 파일을 찾아서 넘겨주는 얇은 셸입니다.

// node_modules/typescript/lib/getExePath.js (일부)
const platformPackageName = "@typescript/" + expectedPackage; // ex) @typescript/typescript-linux-x64
const packageJson = require.resolve(platformPackageName + "/package.json");
exeDir = path.join(path.dirname(packageJson), "lib");

플랫폼별 네이티브 바이너리를 담은 @typescript/typescript-<os>-<arch> 패키지가 optional dependency로 따라 들어오고, tsc는 그걸 실행하는 역할만 합니다. Rust로 다시 짠 Biome이나 Go로 짠 esbuild가 쓰는 것과 같은 패턴입니다.

체감해본 속도

VSCode 벤치마크만큼 큰 프로젝트는 없어서, 간단하게 제네릭 인터페이스와 매핑 타입을 쓰는 150개 파일짜리 모듈을 만들어 strict: true로 tsc --noEmit을 돌려봤습니다.

TypeScript 5.9.3 (JS)   : 1.08s, 0.97s, 0.94s  (3회 반복)
TypeScript 7.0.2 (Go)   : 0.36s, 0.39s, 0.37s  (3회 반복)

150개 파일 규모에서는 약 2.7배 차이였습니다. 이 정도 규모에서는 Node 프로세스 기동 시간 자체가 전체 시간의 큰 부분을 차지해서, VSCode가 보고한 11.9배만큼 벌어지지는 않았습니다. 파일 수가 늘고 타입 추론이 깊어질수록 격차가 커진다는 뜻으로 보입니다.

API가 아직 그대로 열려있지 않습니다

버전만 올리면 끝이 아닌 이유가 따로 있습니다. 기존 typescript 패키지는 ts.createProgram, ts.createLanguageService처럼 JS 객체를 직접 다루는 API를 제공했고, typescript-eslint나 Vue·Svelte·Astro의 타입 체크 플러그인은 전부 이 API 위에서 동작합니다. 7.0 네이티브 컴파일러는 이 API를 아직 공개하지 않았습니다. 대신 package.json의 exports에 unstable이 붙은 새 진입점이 생겼습니다.

import { Program, Checker, Project } from "typescript/unstable/sync";

unstable이라는 이름 그대로, 언제든 모양이 바뀔 수 있다는 뜻입니다. Program이나 Checker 같은 클래스 이름은 비슷해 보여도 과거 API와 1:1로 대응하지 않아서, 저 플러그인들이 단순히 import 경로만 바꿔서 넘어올 수 있는 상황이 아닙니다. 그래서 7.0이 나온 뒤에도 당장 typescript-eslint를 네이티브 컴파일러로 바꿔 쓸 수는 없고, 당분간은 기존 JS 컴파일러와 네이티브 컴파일러가 같이 돌아가는 구간을 지나야 합니다.

TS 6.x 이하 tsgo 프리뷰(2025) TS 7.0
구현 언어 JavaScript Go Go
설치 typescript @typescript/native-preview typescript
명령어 tsc tsgo tsc
Watch/빌드 모드 지원 일부 제한 지원
공개 API ts.createProgram 등 없음 unstable/* (변경 가능)

Watch 모드나 프로젝트 레퍼런스(tsc -b)는 microsoft/TypeScript 리포지토리의 호환 표 기준으로 이미 "done"으로 표시돼 있어서 평소 빌드 스크립트를 그대로 옮겨도 됩니다. 막히는 지점은 거의 항상 API를 직접 호출하는 도구 쪽입니다.

넘어갈 때 체크할 건 하나뿐입니다. tsconfig.json을 수정할 필요는 없고, 빌드·타입체크 단계에서만 쓰는 팀이라면 오늘 바로 올려도 됩니다. 반면 typescript-eslint나 프레임워크 타입 체크 플러그인에 묶여 있다면, 그 도구들이 unstable API로 넘어올 때까지는 JS 컴파일러와 같이 써야 합니다.