TypeScript 컴파일러가 Go로 다시 쓰여서 타입 체크가 10배 빨라졌다
tsc가 느렸던 건 컴파일러가 자바스크립트로 돌아서였다. TypeScript 7이 컴파일러를 Go로 다시 쓰면서 빨라진 이유와 Rust가 아니라 Go를 고른 배경, 작은 프로젝트에서의 체감을 솔직하게 적었다.
#TypeScript #빌드 #Go #프론트엔드
블로그 프론트가 TypeScript 4.9에 멈춰 있었다. 프로젝트가 커지니까 에디터에서 빨간 줄 뜨는 게 굼떠지고, 타입 체크 한 번 도는 게 답답할 때가 있었다. 그러다 TypeScript 7이 컴파일러를 통째로 Go로 다시 썼고, 10배 빨라졌다 는 걸 보고 올려볼까 하고 뜯어봤다. 이 글에서는 기존 tsc가 왜 느렸는지, Go로 옮기니까 왜 빨라졌는지를 정리해본다. 미리 말해두면 이건 내가 겪은 이야기보다는 읽고 정리한 이야기에 가깝다. 이유는 마지막에 적어뒀다. 기존 컴파일러는 자기 자신으로 짜여 있었다 의외로 모르는 사람이 많은데, 그동안 TypeScript 컴파일러(tsc)는 TypeScript로 짜여 있었다 . 즉 결국 자바스크립트로 도는 프로그램이었다. 컴파일러가 자바스크립트로 돌면 두 가지 한계를 그대로 안고 간다. 첫째는 단일 스레드 다. 자바스크립트는 기본적으로 한 번에 한 줄씩 돈다. CPU 코어가 여러 개여도 한 개만 쓴다. 둘째는 GC 멈춤 이다. 메모리를 자동으로 치우는 가비지 컬렉션이 중간중간 돌면서 멈춘다. 타입 체크는 코드 전체의 타입 관계를 그래프로 그려서 끝없이 따라다니는 작업이라, 위 두 한계에 정통으로 걸린다. 프로젝트가 커질수록 기하급수로 느려졌던 이유다. 그래서 Go로 다시 썼다, 왜 빨라졌나 TypeScript 7은 컴파일러를 Go 로 처음부터 다시 짰다. 빨라진 이유는 두 개다. 하나는 네이티브로 컴파일된다 는 점이다. Go는 기계어로 떨어진다. 자바스크립트처럼 런타임이 한 줄씩 해석하는 게 아니라, CPU가 바로 먹는 코드로 돈다. 다른 하나는 공유 메모리 병렬이 된다 는 점이다. Go는 여러 코어를 진짜로 동시에 굴린다. 자바스크립트가 못 하던 바로 그것이다. 타입 그래프를 여러 갈래로 나눠 동시에 훑을 수 있다. 숫자로 보면 확실하다. 공개된 벤치마크에서 VSCode 코드베이스(150만 줄)가 89초에서 8.74초로, 10.2배 빨라졌다고 한다. 근데 왜 Rust가 아니라 Go였나 Vite는 Rust로 갔는데(지난 글) TypeScript는 왜 Go냐는 궁금증이 들었다. 이유가 재밌다. 기존 tsc는 그래프를 타고 돌아다니는 구조 에 GC를 적극적으로 쓰는 코드였는데, Go가 그 구조랑 메모리 모델이 잘 맞아서 거의 1:1로 포팅 하기 쉬웠다고 한다. Rust로 갔으면 소유권 모델 때문에 구조를 다시 설계해야 했을 거고, 그러면 기존 동작과 미묘하게 달라질 위험이 있었다. 동작을 그대로 옮기면서 속도만 올리려면 Go가 합리적인 선택이었던 거다. 새 컴파일러는 tsgo 라는 실행 파일로 미리 써볼 수 있었고, 2026년 초에 정식(7.0)으로 안정화됐다. Bloomberg, Figma, Google, Slack, Vercel 같은 데가 미리 프로덕션에서 굴려봤다고 한다. 써보는 방법은 간단하다 미리보기 시절부터 별도 패키지로 나와 있어서, 기존 프로젝트를 안 건드리고 옆에서 돌려볼 수 있다. 같은 tsconfig를 읽으니 명령어만 바꾸면 된다. # 설치하고 npm install -D @typescript/native-preview # 기존 tsc 자리에 tsgo를 넣어서 타입 체크만 돌려본다 npx tsgo --noEmit # package.json 에서는 이렇게 바꾸는 식이다 "scripts": { "typecheck": "tsgo --noEmit", "build": "tsgo --noEmit vite build" } 빌드 파이프라인에서 tsc가 하던 역할이 타입 체크뿐이라면(Vite 프로젝트가 대개 그렇다, 트랜스파일은 esbuild가 한다) 이 한 줄 교체로 끝난다. 다만 7.0에서 몇 가지 옛날 옵션이 정리됐다. target이 ES5 아래로 내려가는 설정이나 옛날 모듈 해석 방식 같은 건 더 이상 안 먹는다고 하니, tsconfig가 오래됐다면 이 부분부터 확인해야 한다. 4.9에서 올리면 뭐가 걸리나 버전 갭이 커서(4.9에서 7) 그동안 느슨하게 넘어가던 타입이 새로 걸릴 가능성이 높다. 5.x를 거치면서 기본값이 엄격해진 옵션들이 있어서다. 근데 이건 오히려 그동안 숨어 있던 허점이 드러나는 거라, 잡고 나면 코드가 더 단단해진다. 속도 때문에 올렸다가 타입 안정성까지 챙기는 셈이다. 내 프로젝트는 3초가 0.3초 되는 정도다 10배라는 숫자에 혹했는데, 정작 내 프로젝트에서 tsc가 느려서 답답했던 적이 있었나 생각해보니 없었다. 이 블로그 프론트는 여전히 TypeScript 4.9 다. 이 글을 다시 손보는 2026년 9월에 package.json을 열어봐도 4.9.3 그대로다. 빌드 전체가 6초쯤 걸리는데 그중 타입 체크가 몇 초일 테고, 그게 10배 빨라져 봐야 체감은 크지 않다. 큰 코드베이스에서 일해본 적이 없어서 이 변화의 진짜 의미를 아직 모르는 것 같다. 수십만 줄짜리에서 타입 체크가 몇 분씩 걸린다는 이야기는 들었는데, 내 경험이 아니라 남의 이야기다. 그래서 이 글은 "겪은 것"보다 "읽은 것"에 가깝다. 위에 적은 명령어도 문서 기준이지 내 프로젝트에서 돌려본 게 아니다. 나중에 큰 프로젝트를 만지게 되면 그때 실제 수치를 붙여서 다시 써야겠다.