Back

TypeScript 7과 Project Corsa: Go로 다시 쓴 10배 빠른 컴파일러, 총정리

2025년 3월, Anders Hejlsberg가 카메라 앞에서 아무도 예상 못 한 말을 꺼냈어요.

"TypeScript 컴파일러를 Go로 포팅합니다."

Rust가 아니에요. 점진적 리팩토링도 아니고요. 컴파일러, 언어 서비스, 타입 체커 — TypeScript의 핵심 전부를 Go로 통째로 옮기겠다는 선언이에요. Microsoft는 이 프로젝트를 Project Corsa라 부르고, 지금 TypeScript 7.0으로 나오고 있어요.

숫자부터 볼까요. VS Code 코드베이스가 TypeScript 150만 줄이에요. 기존 tsc로 컴파일하면 약 78초. 새 Go 기반 컴파일러 tsgo로 돌리면? 7.5초. 2배도 아니고 10.4배 빨라진 거예요.

그냥 툴 하나 바뀌는 정도가 아니에요. TypeScript가 생긴 지 12년 만에 가장 큰 변화고, 빌드하고 배포하고 생각하는 방식 자체가 달라질 수 있어요. 하나씩 뜯어볼게요.

대체 왜 다시 쓰는 건가요?

Project Corsa를 이해하려면, 기존 컴파일러가 어디서 한계에 부딪혔는지부터 알아야 해요.

TypeScript 컴파일러는 원래 TypeScript 자체로 쓰였어요. 10년 넘게 잘 돌아갔는데, TypeScript가 웹 개발 대세가 되면서(2025년 8월에 GitHub에서 JavaScript를 처음 추월했어요) 자기 성공을 감당하기 힘들어진 거예요.

한계가 어디서 터졌나

  • 대기업 코드베이스가 너무 커졌어요. Google, Microsoft, Stripe 같은 데서 TypeScript 수백만 줄을 돌리고 있거든요. 이 정도 규모면 IDE가 버벅거려요. 빨간 밑줄이 몇 초 늦게 뜨고, 자동 완성에 2-3초 걸리고, 프로젝트 전체 이름 바꾸기가 타임아웃 나요.

  • CI/CD가 발목을 잡았어요. 패키지 수백 개짜리 모노레포에서 tsc --build가 전체 파이프라인 중 가장 느린 단계인 경우가 많았어요. 타입 체크만 10분 넘는 경우도 있었고요.

  • 싱글 스레드의 한계. JavaScript 런타임은 태생적으로 싱글 스레드잖아요. 타입 체킹이든 파싱이든 추론이든 전부 코어 하나에서 순서대로 돌아가고, M4 Pro에 코어가 16개 있어도 나머지 15개는 놀고 있었다는 거예요.

왜 하필 Go인가요?

다들 이걸 궁금해하더라고요.

Rust는 왜 안 됐냐면, 성능은 최고겠지만 개발 속도가 문제예요. TypeScript 컴파일러 코드가 클로저를 많이 쓰고, 재귀 데이터 구조가 많고, 판별 유니온 패턴 매칭이 많은 함수형 스타일이거든요. Rust 소유권 모델이 이 스타일이랑 계속 충돌해요. 팀에서는 Rust로 쓰면 3-5배 더 오래 걸리고 아키텍처부터 뜯어고쳐야 한다고 봤어요.

결국 Go가 맞았던 이유:

  1. 코드 스타일이 딱 맞아요. TypeScript 컴파일러 코드가 사실 객체지향보다는 절차적·함수형에 가까워요. Go의 인터페이스, 일급 함수, 단순한 구조체가 기존 코드랑 잘 대응돼요.

  2. 고루틴 덕에 병렬 처리가 쉬워요. 스레드를 직접 관리할 필요 없이 고루틴으로 가볍게 병렬 처리할 수 있어요. 파일별 타입 체킹을 동시에 돌리기 딱이에요.

  3. 성능이 일정해요. Go GC가 저지연 앱에 최적화되어 있어서, V8 GC처럼 갑자기 멈추는 일이 없어요. IDE 반응성에 꼭 필요한 부분이에요.

  4. 바이너리 하나로 끝나요. Go 바이너리는 Node.js 없이 단독으로 돌아가요. npm install 필요 없이 받아서 바로 실행하면 돼요.

  5. 팀이 빨리 적응했어요. Rust보다 Go를 훨씬 빨리 배우면서도 필요한 성능 향상은 다 달성할 수 있었대요.

기술적으로 뭐가 달라졌나요?

Project Corsa는 "같은 컴파일러가 그냥 빨라진 것"이 아니에요. 아키텍처 자체가 바뀌었어요.

아키텍처: 이전 vs 이후

TypeScript 5.x/6.x (JavaScript 기반):

소스 파일 → Scanner → Parser → Binder → Type Checker → Emitter
           ↑                                              ↓
      싱글 스레드, 순차 파이프라인                     .js + .d.ts
      V8 위에서 Node.js로 실행
      설치 크기 ~14MB (tsc + 런타임)

TypeScript 7.x (Go 기반):

소스 파일 → Scanner → Parser → Binder → Type Checker → Emitter
           ↑          ↑                    ↑            ↓
        병렬      병렬 파싱         멀티 스레드       .js + .d.ts
        파일 I/O                   타입 체킹
        네이티브 바이너리, ~25MB 독립 실행
        런타임 의존성 없음

뭐가 핵심이냐면요:

  1. 파일을 한꺼번에 읽어요. 고루틴으로 파일을 동시에 읽고 파싱해요. 수천 개 파일의 프로젝트에서 이것만으로도 2-3배 빨라져요.

  2. 타입 체킹도 병렬이에요. 가장 무거운 단계인 타입 체킹이 독립 모듈끼리 동시에 돌아가요. 서로 안 엮인 파일들은 한꺼번에 체크되니까, 10배 개선의 핵심이 여기 있어요.

  3. 메모리를 공유해요. JavaScript 워커 스레드는 데이터를 직렬화해서 넘겨야 하는데, Go 고루틴은 메모리를 그냥 같이 써요. 심볼 테이블 같은 걸 복사할 필요가 없어요.

  4. 데이터 구조가 더 효율적이에요. Go 네이티브 slice, map이 V8 힙 객체보다 메모리 관리가 깔끔해요. GC 부담이 줄고 캐시 효율도 올라가요.

tsgo CLI

새 컴파일러는 tsgo라는 이름으로 나오고, 기존 tsc랑 같이 쓸 수 있어요:

# 기존 TypeScript 컴파일러 (TS 6.x, 여전히 돌아감) npx tsc --build # 새 Go 기반 컴파일러 npx tsgo --build # 독립 바이너리로 직접 (Node.js 없이) tsgo --build

tsgotsconfig.json을 그대로 받고 출력도 같아요. tsc로 되는 코드면 tsgo로도 되고, 나오는 JS랑 .d.ts도 동일해야 돼요.

TypeScript 6.0이 다리 역할

TypeScript 6.0은 JavaScript 시대에서 Go 시대로 넘어가는 징검다리에요:

타임라인:
TS 5.9 (2025년 말)    → 마지막 "일반" 릴리스
TS 6.0 (2026년 2월)   → 징검다리: deprecated 처리 + 준비
TS 7.0 (2026년 중반)  → Go 기반 컴파일러 (Project Corsa)

TS 7.0 대비해서 TS 6.0에서 바뀌는 것들:

  • target: "es5" deprecated. TS 7에서 ES5 출력 안 돼요. 필요하면 Babel이나 SWC를 따로 붙이세요.
  • 레거시 모듈 해석 deprecated. "moduleResolution": "node" (구버전)이랑 "classic" 못 써요. "node16", "nodenext", "bundler" 쓰세요.
  • 기본값이 바뀌어요. 기본 target"es2025", 기본 module"nodenext"로.
  • Temporal API 타입 추가. JavaScript Temporal API 타입이 기본 포함.

10배가 진짜예요?

"10배 빠르다"는 소리만 들으면 과장 같잖아요. 맥락을 좀 붙여볼게요.

풀 빌드

코드베이스TS 라인 수tsc (TS 6.x)tsgo (TS 7.x)몇 배?
VS Code150만~78초~7.5초10.4x
Playwright~80만~45초~3.5초12.9x
TypeORM~35만~28초~2.8초10x
중간 규모 (5만 줄)5만~4초~0.8초5x
작은 앱 (5천 줄)5천~1.2초~0.5초2.4x

보이죠? 프로젝트가 클수록 효과가 커요. 파일이 많으면 병렬 처리를 그만큼 더 쓸 수 있으니까요. 파일 20개짜리 사이드 프로젝트에서는 체감이 크지 않아요.

IDE 체감 (Language Service)

사실 대부분 개발자한테는 이게 더 와닿을 거예요:

500개 파일짜리 TypeScript 프로젝트를 열었을 때

TS 6.x 기준:
  프로젝트 로딩:         4-6초
  첫 자동 완성까지:      2-3초
  정의로 이동:           500ms-1초
  타입 호버:            200-500ms
  전체 이름 바꾸기:      5-15초

TS 7.x (tsgo) 기준:
  프로젝트 로딩:         0.5-1초
  첫 자동 완성까지:      200-400ms
  정의로 이동:           50-150ms
  타입 호버:            30-100ms
  전체 이름 바꾸기:      1-3초

빌드 속도보다 이쪽이 체감 효과가 더 클 수 있어요. IntelliSense가 빨라지면 기다리는 시간이 줄고, 흐름이 안 끊기고, 코딩 자체가 더 매끄러워지거든요.

메모리도 줄었어요

VS Code 코드베이스 타입 체킹 기준

TS 6.x (Node.js):
  최대 메모리:  ~4.2 GB
  평균:        ~3.1 GB

TS 7.x (tsgo):
  최대 메모리:  ~1.8 GB
  평균:        ~1.2 GB

줄어든 양: 약 57%

CI 러너에 RAM이 적어도 되고, 노트북에서 스와핑 없이 개발할 수 있고, Docker 메모리 제한도 더 타이트하게 잡을 수 있어요.

뭐가 깨지나요?

TypeScript 7은 동작 호환을 목표로 하고 있지만, "목표"랑 "실제"는 다를 수 있어요.

🔴 고위험: Compiler API 플러그인

TypeScript Compiler API(ts.createProgram, ts.transform 등)를 쓰고 있다면 가장 조심해야 해요. Go 기반 컴파일러는 API가 달라서, 기존 JavaScript Compiler API로 만든 커스텀 트랜스포머가 tsgo에서는 안 돌아가요.

// ❌ tsgo에서 안 되는 코드 import * as ts from 'typescript'; const transformer: ts.TransformerFactory<ts.SourceFile> = (context) => { return (sourceFile) => { return ts.visitEachChild(sourceFile, visitor, context); }; };

영향받는 대표 도구:

  • ts-morph (코드 조작)
  • ttypescript (커스텀 트랜스포머 로더)
  • ts.LanguageServicePlugin 계열 전부
  • Compiler API를 깊게 쓰는 빌드 도구

TS 7에서 gRPC/IPC 기반의 새 크로스 랭귀지 API가 나올 예정이지만, 기존 플러그인은 재작성해야 해요.

🟡 중위험: Strict가 기본 ON

TypeScript 7부터는 strict: true가 기본이에요. tsconfig에 명시 안 했으면 아래가 전부 켜져요:

{ "compilerOptions": { "strict": true, "strictNullChecks": true, "strictFunctionTypes": true, "strictBindCallApply": true, "strictPropertyInitialization": true, "noImplicitAny": true, "noImplicitThis": true, "alwaysStrict": true, "useUnknownInCatchVariables": true } }

strict를 안 쓰던 코드베이스라면 업그레이드하는 순간 에러가 수백~수천 개 쏟아져요. 지금 상태 유지하려면 "strict": false를 직접 넣으세요.

🟢 저위험: 출력 미세 차이

tsgo가 내놓는 JS는 tsc랑 기능적으로 같지만, 공백이나 소스맵 컬럼 번호에 미세한 차이가 있을 수 있어요. 대부분 프로젝트에선 눈에 안 보여요. 출력 JS를 글자 단위로 비교하는 스냅샷 테스트가 있다면 깨질 수 있는데, 스냅샷 업데이트하면 끝이에요.

지금부터 준비하는 법

TS 7 정식 나올 때까지 기다릴 필요 없어요.

1. tsconfig.json 점검

npx tsgo --build --noEmit 2>&1 | grep -i "deprecated"

직접 확인할 것:

  • target: "es5""es2020" 이상
  • moduleResolution: "node""node16" 또는 "bundler"
  • module: "commonjs""node16" 또는 "nodenext" 검토

2. Strict 모드 켜보기

npx tsc --strict --noEmit 2>&1 | wc -l

에러가 감당할 만하면 지금 켜세요. 수천 개면 하나씩 점진적으로:

{ "compilerOptions": { "strictNullChecks": true, "noImplicitAny": true, "strictFunctionTypes": true } }

3. Compiler API 의존성 확인

grep -r "from 'typescript'" node_modules/*/src/ 2>/dev/null | head -20

빌드 툴이나 린트 플러그인 중에 Compiler API를 깊이 쓰는 게 있는지 확인해두세요.

4. tsgo로 미리 돌려보기

npm install -D [email protected] npx tsgo --noEmit # 속도 비교 time npx tsc --noEmit time npx tsgo --noEmit

생태계는 어떻게 되나요?

번들러·빌드 도구

Vite / Rolldown / esbuild / SWC: 트랜스파일은 자체적으로 하고 타입 체크만 tsc에 맡기는 구조라 코어 기능에는 영향 없어요. CI에서 tsgo로 바꿔 타입 체크를 더 빠르게 할 수 있어요.

webpack (ts-loader): Compiler API를 직접 쓰고 있어서 tsgo 호환 업데이트가 필요해요.

IDE

VS Code: Go 기반 언어 서비스를 도입할 예정이에요. 큰 프로젝트에서 IntelliSense가 확 빨라질 거예요. VS Code 팀이 이미 VS Code 자체 코드베이스에서 tsgo를 쓰고 있어요.

프레임워크

Next.js / Nuxt / Remix / SvelteKit: 빌드할 때 타입 체크에 tsc를 쓰니까, tsgo로 바꾸면 코드 수정 없이 바로 빨라져요.

Angular: ngc가 Compiler API를 광범위하게 써서 마이그레이션이 가장 복잡한 축에 들어요. Angular 팀이 작업 중이에요.

"TypeScript가 TypeScript로 안 쓰였는데 그래도 TypeScript야?"

발표 직후에 이런 논쟁이 꽤 있었어요. Self-hosting이 깨졌다는 의견도 있었고, JavaScript 개발자를 위한 언어의 핵심이 Go라니 아이러니하다는 반응도 있었고요.

현실적으로 보면요: TypeScript라는 언어 자체는 하나도 안 변해요. .ts 파일, 타입 어노테이션, tsconfig.json — 전부 그대로. 컴파일러는 구현 방법일 뿐이에요. Python으로 가장 많이 쓰는 구현체가 C로 쓴 CPython인 것처럼, TypeScript도 더 빠른 언어로 만든 컴파일러를 쓰게 되는 거예요.

솔직히 78초가 7.5초로 줄어드는 걸 직접 보니까 논쟁이 금방 사그라들던데요.

더 넓게 보면: JS 툴링의 "네이티브 전환" 흐름

TypeScript 7은 단독 사건이 아니에요. JavaScript 툴링 전체가 이 방향으로 가고 있어요:

도구원래 언어뭘로 바꿨나몇 배?
TypeScript 7 (tsgo)TypeScriptGo10x
Rolldown (Rollup 대체)JavaScriptRust10-15x
esbuildGo100x vs webpack
SWC (Babel 대체)JavaScriptRust20x
Biome (ESLint+Prettier 대체)JavaScriptRust25x
Oxc (파서/린터)JavaScriptRust50x

패턴이 보이죠? 성능이 중요한 인프라는 시스템 언어로 옮기고, 개발자가 쓰는 API는 JavaScript/TypeScript로 유지하는 거예요. 코딩할 때 달라지는 건 없는데 밑단이 네이티브로 바뀌는 거예요.

JavaScript가 죽는 게 아니에요. 역할이 분화되고 있는 거예요. 앱 로직, UI, 비즈니스 규칙은 JavaScript/TypeScript가 하고, 컴파일·린팅·번들링은 멀티코어와 효율적인 메모리를 쓸 수 있는 도구한테 맡기는 구조요.

앞으로 일정

단기 (2026년 Q1-Q2)

  • TypeScript 7.0 베타 사용 가능
  • tsgo CLI npm 설치 가능
  • 주요 번들러·프레임워크 tsgo 통합 시작

중기 (2026년 Q3-Q4)

  • TypeScript 7.0 안정판 출시
  • VS Code가 Go 기반 언어 서비스를 기본으로 전환
  • 플러그인 생태계 새 API로 이동

장기 (2027년~)

  • TypeScript 6.x (tsc) 유지보수 모드
  • 새 기능은 Go에서 먼저 구현
  • JS 기반 컴파일러에서는 불가능했던 것들 (패키지 경계 넘는 전체 프로그램 분석 같은) 가능

정리하면

TypeScript 7과 Project Corsa는 TypeScript가 생긴 이래 가장 큰 변화예요. Self-hosted JavaScript 컴파일러에서 Go 네이티브 바이너리로의 전환은 단순히 빨라지는 게 아니라, 새로운 가능성이 열리는 아키텍처 전환이에요.

대부분 개발자한테는 가장 좋은 의미로 별거 아닌 업그레이드가 될 거예요. 코드 그대로, tsconfig 그대로, 그런데 전부 빨라져요. 훨씬.

도구 만드는 분들이나 프레임워크 개발자한테는 진짜 마이그레이션 작업이 필요해요. Compiler API 변경이 핵심인데, 지금부터 tsgo --noEmit로 한번 돌려보세요.

78초짜리 빌드가 7.5초로 줄었는데 안 웃으면, 뭘 봐야 웃을 수 있는 거예요? 😄

TypeScriptGocompilerperformancetoolingJavaScriptdeveloper-toolsProject Corsa

관련 도구 둘러보기

Pockit의 무료 개발자 도구를 사용해 보세요