목록으로

TypeScript 7.0, 컴파일러가 Go로 다시 태어났다

10배 빨라진 네이티브 컴파일러의 원리와 브레이킹 체인지, 그리고 직접 올려보며 겪은 것들까지 정리했다.

· 6분 읽기

2026년 7월 8일, TypeScript 7.0이 정식 릴리즈됐다.

버전 번호만 보면 여느 메이저 업데이트 같지만, 이번엔 결이 다르다. 문법이 추가된 게 아니라 컴파일러 자체가 통째로 바뀌었다. 10년 넘게 TypeScript로 작성되어 있던 컴파일러가 Go로 재작성됐고, 그 결과 풀 빌드 기준 8~12배, 조건에 따라 최대 16배까지 빨라졌다.

작년에 "10x 프로젝트"라는 이름으로 예고됐던 그 작업이 드디어 npm install -D typescript 한 줄로 설치되는 정식 버전이 된 것이다. 이 글에서는 무엇이 어떻게 바뀌었는지, 숫자가 실제로 의미하는 게 뭔지, 올릴 때 뭘 조심해야 하는지를 정리한다. 마지막에는 이 블로그에 직접 올려보다가 겪은 사고도 하나 공유한다.

왜 Go로 다시 썼나

TypeScript 컴파일러는 원래 TypeScript로 작성되어 있었다. 자기 자신을 자신으로 컴파일하는 구조는 우아하지만, 성능 관점에서는 태생적 한계가 있었다.

첫째, JavaScript 런타임 위에서 돌기 때문에 JIT 워밍업, GC 부담, 객체 레이아웃 오버헤드를 피할 수 없다. 둘째, 더 치명적인 건 공유 메모리 멀티스레딩이 안 된다는 것. JavaScript의 워커는 메모리를 공유하지 못하니, 거대한 타입 그래프를 여러 스레드가 나눠 검사하는 구조를 만들 수 없었다. 코드베이스가 커질수록 체크 시간이 선형으로 늘어나는 걸 지켜볼 수밖에 없었다.

Go 포트는 이 두 한계를 정면으로 푼다. 네이티브 코드라 워밍업이 없고, 고루틴 기반 공유 메모리 병렬화로 파싱·타입 체크·방출(emit)을 동시에 진행한다. 중요한 건 이게 "새로 만든 컴파일러"가 아니라 기존 컴파일러의 포트라는 점이다. 타입 체킹의 동작을 그대로 옮기는 걸 원칙으로 했기 때문에, 6.0에서 깨끗하게 컴파일되던 코드는 7.0에서도 동일하게 컴파일되는 걸 목표로 한다. 새 언어로 다시 만들면서 동작까지 새로 설계했다면 생태계가 감당할 수 없었을 것이다.

참고로 개발 중에 tsgo라는 이름으로 불리던 그 바이너리가 맞다. 정식 릴리즈에서는 그냥 tsc다. 쓰던 명령어 그대로 쓰면 된다.

숫자로 보는 성능

공식 발표에 실린 실측 벤치마크가 흥미롭다. 실제 오픈소스 프로젝트들의 풀 빌드 기준이다.

프로젝트6.07.0배율
VS Code125.7초10.6초11.9x
Sentry139.8초15.7초8.9x
Bluesky24.3초2.8초8.7x
Playwright12.8초1.5초8.7x
tldraw11.2초1.5초7.7x

기본값은 타입 체커 워커 4개(--checkers 4)인데, 코어가 남으면 더 줄 수 있다. VS Code 프로젝트에 --checkers 8을 주면 16.7배까지 올라간다. 메모리 사용량도 6~26% 줄었다. 네이티브 코드가 메모리를 더 먹을 거라는 직관과 반대인데, JS 객체 오버헤드가 사라진 영향이 크다.

체감으로 와닿는 건 CI 쪽 후기다. Slack은 CI 타입 체크가 7.5분에서 1.25분으로 줄면서 머지 큐가 40% 줄었다고 했다. 타입 체크가 병목이던 팀이라면 이 업그레이드 하나가 캐시 튜닝 몇 달치보다 나을 수 있다.

에디터가 더 크게 바뀐다

빌드 속도보다 일상에 더 영향을 주는 건 에디터다. 7.0은 언어 서비스를 LSP(Language Server Protocol) 기반으로 재구축했다. 기존 tsserver는 LSP 이전 시대에 만들어진 독자 프로토콜이었는데, 이번에 표준으로 갈아탄 것이다.

수치도 함께 공개됐다. 실패하는 명령이 80% 이상, 크래시가 60% 이상 줄었고, VS Code 프로젝트를 열고 첫 에러가 표시되기까지 17.5초 걸리던 게 1.3초가 됐다. 대형 모노레포에서 파일 열 때마다 스피너를 보던 경험이 있다면, 이게 어떤 의미인지 알 것이다.

VS Code에서는 "TypeScript 7" 확장을 설치하면 바로 쓸 수 있고, 추후 기본 내장될 예정이다. 파일 워처도 Parcel의 워처를 Go로 포팅해 통째로 갈았다. 워치 모드가 파일 변경을 놓치거나 CPU를 태우던 고질병들이 상당 부분 해소됐다.

브레이킹 체인지: 6.0의 예고가 현실이 됐다

7.0의 브레이킹 체인지는 대부분 "6.0에서 deprecated 경고였던 것들이 하드 에러가 된 것"이다. 6.0을 건너뛰고 5.x에서 바로 7로 점프하려는 경우 특히 주의해야 한다.

기본값이 바뀐 것들:

jsonc
// 7.0의 암묵적 기본값
{
  "compilerOptions": {
    "strict": true,            // 이제 기본 켜짐
    "module": "esnext",
    "types": [],               // @types 자동 포함 안 됨, 명시 필요
    "rootDir": "./"
  }
}

strict가 기본값이 된 게 가장 크다. 새 프로젝트는 환영할 일이지만, strict 없이 살아온 레거시는 올리는 순간 에러가 쏟아진다. types: [] 기본값도 은근히 아프다. 전역 타입(@types/node 등)에 의존하고 있었다면 types 배열에 명시해야 한다.

제거된 것들:

  • target: es5 — ES5 트랜스파일 지원 종료. IE는 이제 정말 보내주자
  • moduleResolution: node(node10), classicbundler 또는 node16 계열로
  • baseUrlpaths만으로 해석. baseUrl 기반 절대 임포트를 쓰던 프로젝트는 paths 재정의 필요
  • module: amd / umd / system — 번들러 이전 시대의 유산 정리
  • esModuleInterop: false, allowSyntheticDefaultImports: false — 이제 끌 수 없다
  • import assertion의 assert 키워드 — with로 교체

그 외에 두 가지가 눈에 띈다. 템플릿 리터럴 타입의 유니코드 처리가 코드 포인트 단위로 바뀌어서 이모지를 다루는 타입 레벨 문자열 조작이 있다면 결과가 달라질 수 있다. JavaScript 파일 분석에서 Closure 스타일 JSDoc(@enum 등) 특례도 제거됐다.

마이그레이션은 이렇게

경험상 순서가 중요하다.

  1. 먼저 6.0으로 올려서 deprecation 경고를 다 잡는다. 6.0은 경고만 하고 7.0은 에러를 낸다. 6.0이 마이그레이션 리허설인 셈이다.
  2. tsconfig.json을 새 기본값에 맞춘다. rootDir 명시, types 배열 명시, baseUrl 쓰고 있었다면 paths로 전환.
  3. npm install -D typescript@7로 올리고 tsc --noEmit을 돌린다.
  4. 문제가 있는 도구가 있다면 6을 나란히 둘 수 있다:
sh
# 7을 메인으로, 6을 별칭으로 공존
npm install -D typescript@7
npm install -D typescript6@npm:@typescript/typescript6
# tsc는 7, tsc6은 6

모노레포라면 --builders 옵션으로 프로젝트 빌드 병렬화도 조절할 수 있고, 컨테이너처럼 코어가 제한된 환경에서는 --singleThreaded로 끌 수도 있다.

직접 올려보다 겪은 사고

이 블로그를 Next.js 16.2로 올리는 김에 TypeScript도 7.0.2로 올려봤다. tsc --noEmit은 아무 문제 없이, 그리고 확실히 빠르게 통과했다. 그런데 next build가 이상하게 죽었다.

로그를 보니 이런 메시지가 있었다.

It looks like you're trying to use TypeScript but do not have
the required package(s) installed.
Installing devDependencies (npm):
- typescript

TypeScript 7.0.2가 멀쩡히 설치되어 있는데 Next.js가 "TypeScript 미설치"로 판단하고, 빌드 도중 npm으로 5.x를 강제 설치해버린 것이다. bun으로 관리하던 node_modules는 그 과정에서 엉망이 됐다.

원인은 위에서 언급한 API 문제다. 7.0은 프로그래매틱 API 없이 출시됐다. Next.js는 TypeScript를 감지하고 설정을 읽을 때 컴파일러 API를 사용하는데, 7.0에는 그 API가 없으니 "설치 안 됨"으로 취급한 것이다. 결국 이 블로그는 5.9.3으로 되돌렸고, TS 7 네이티브 지원이 들어간 Next.js 16.3 안정판을 기다리기로 했다.

같은 이유로 컴파일러 API를 내장하는 도구들이 전부 같은 상황이다. Vue, Svelte, Astro, MDX, Angular 템플릿의 타입 지원(Volar 계열)이 아직 7과 호환되지 않는다. API가 다시 생기는 건 7.1부터로 예고되어 있고, 그마저도 6과는 다른 구조가 될 예정이다.

그래서 지금 올려야 하나

정리하면 판단 기준은 하나다. 컴파일러 API에 기대는 도구를 쓰고 있는가.

  • 순수 tsc CLI + 에디터만 쓴다 → 지금 올려도 된다. CI가 느린 팀일수록 이득이 크다
  • Vite + React/바닐라 TS → 대체로 문제없다. esbuild/SWC가 트랜스파일하고 tsc는 체크만 하는 구조라면 7의 수혜만 받는다
  • Next.js → 16.3부터. 그 전 버전에서는 위의 사고가 재현된다
  • Vue / Svelte / Astro / Angular → 7.1과 각 도구의 대응을 기다리는 게 맞다
  • 컴파일러 API로 커스텀 도구를 만들었다 → 6과 병행 운용하며 7.1의 새 API를 준비하자

릴리즈 주기는 앞으로 3~4개월로 예고됐다. 7.1에서 API가 돌아오면 생태계 공백은 빠르게 메워질 것이다.

마무리

TypeScript 7.0은 기능 릴리즈가 아니라 기반 교체다. 문법은 그대로인데 도구가 10배 빨라졌다는 건, 그동안 "타입 체크가 느려서" 포기했던 것들을 다시 테이블에 올릴 수 있다는 뜻이기도 하다. 커밋마다 풀 체크를 돌리는 CI, 저장할 때마다 전체 프로젝트를 검사하는 에디터 설정, 타입 레벨로 더 무겁게 모델링하는 설계까지.

다만 생태계의 절반은 아직 7.1을 기다리고 있다. 내 프로젝트가 어느 쪽인지 확인하고 움직이면, 이번 업그레이드는 최근 몇 년의 어떤 메이저보다 체감이 클 것이다.


참고: TypeScript 7.0 공식 발표, TypeScript 7.0 Beta 발표

댓글