- Published on
TypeScript 를 Rust 로 다시 쓰는 데 42만 달러 — 진짜 목적은 V8 isolate 였다 (You can rewrite typescript in rust for $420k)
- Authors

- Name
- Nostrss
- Github
- Github
출처: You can rewrite typescript in rust for $420k — Theo - t3.gg. 영상의 내용을 기록으로 남겨두기 위해 블로그로 작성했다.
Theo 가 TypeScript 컴파일러, 타입 체커, LSP 를 통째로 Rust 로 다시 쓴 TS Rust 를 공개했다. Codex 토큰 40만 달러를 태우고 실패했고, Opus 5.5 로 2만 달러어치를 돌려 2주 만에 끝냈다 — 본인은 코드를 한 줄도 읽지 않았다고 한다. 그런데 영상의 핵심은 속도가 아니다. Go 로 짠 공식 TypeScript 7 이 이미 충분히 빠른데 왜 또 Rust 인가, 그 답이 이 글의 질문이다.
숫자는 전부 Theo 본인의 주장이고, 벤치마크 원본은 영상에서만 확인할 수 있다.
TS → JS 는 쉽고, 타입 체크가 어렵다
function logUser(user: { name: string }) {
console.log(user.name)
}
이 코드는 브라우저에서 바로 돌지 않는다. : { name: string } 이 JavaScript 문법이 아니기 때문이다. 그런데 이걸 고치는 건 타입 표기를 지우는 것뿐이다.
function logUser(user) {
console.log(user.name)
}
그래서 변환(transpile)은 오래전부터 빠른 도구가 많았다. 대표가 Figma CTO 였던 Evan Wallace 가 Go 로 짠 esbuild 다. 하지만 esbuild 는 타입을 지울 뿐 검사하지 않는다. 진짜 비싼 일은 타입이 맞는지 확인하는 쪽이고, 큰 코드베이스들은 결국 "브라우저에 올리는 경로"와 "타입 체크 경로"를 분리했다. Theo 는 Twitch 시절 저장 후 화면 반영까지 30초~1분 걸리던 걸 이 분리로 5초 아래로 줄였다고 한다.
타입 체커가 어려운 이유는 TypeScript 의 타입 시스템이 JavaScript 의 이상한 동작을 전부 충실하게 인코딩하기 때문이다. 튜링 완전해서 타입 시스템만으로 Doom 을 돌린 사람도 있다. 이걸 JS 가 아닌 언어로 옮기는 건 "영어의 문법을 스페인어로 설명하는 것"과 같다 — 그 복잡도에 곱하기 100.
왜 Microsoft 는 Go 를 골랐나 — GC 가 컴파일러에선 문제가 안 된다
그래도 Microsoft 는 TSC 를 Go 로 포팅했다(typescript-go, 이른바 TSGO = TypeScript 7). Go 혐오자를 자처하는 Theo 도 이 선택은 맞다고 본다. 이유는 셋이다.
- goroutine 기반 동시성 — 코어를 더 쓰는 게 포팅의 주 목표였다
- JS 와 닮은 문법 — 원본 함수와 포팅된 함수를 나란히 놓고 비교하기 쉽다
- 가비지 컬렉션 — 메모리를 직접 관리하지 않아도 된다
GC 는 원래 Go 의 약점이다. GC 가 도는 순간 실행이 멈추니 응답 지연이 튄다. 그런데 이게 컴파일러에서는 왜 괜찮은가. Theo 의 계산을 그대로 옮기면 이렇다.
// 요청 1000개가 각각 25ms, 그중 1개만 GC 때문에 300ms 라면
const normal = 999 * 25 // 24975
const withGc = normal + 300 // 25275
withGc / (1000 * 25) // 1.011 — 전체로 보면 약 1% 느려질 뿐
요청 하나하나의 지연이 중요한 웹 서버에서는 300ms 짜리 한 건이 치명적이다. 하지만 몇 초~몇 분 걸리는 컴파일 한 번 안에서 GC 가 열 번, 백 번 돌아도 전체 시간에서는 묻힌다. 느린 JS 도구를 빠르게 만들고 동시성을 얻는 용도라면 Go 는 최선의 선택 중 하나라는 게 Theo 의 결론이다.
에이전트는 JS 가 아니라 Go 를 옮겼다
이 프로젝트에서 제일 재밌는 대목이다. Theo 는 TS Rust 를 새 모델이 나올 때마다 던져보는 "불가능한 과제"로 써왔다. OpenAI 모델로는 호환성 84% 가 한계였다 — 남은 16% 는 갈수록 더 어려운 엣지 케이스뿐이니까.
Opus 5.5 는 다르게 풀었다. crate 목록을 열어보면 go std 가 있다. Go 표준 라이브러리를 Rust 로 포팅해 놓고, Microsoft 의 Go 버전을 한 줄씩 그대로 옮긴 것이다. runtime.rs 에는 goroutine 이 Rust 로 재구현돼 있다. Theo 도 남이 트위터에서 지적하기 전까지 몰랐다고 한다.
그래서 첫 결과는 Go 버전보다 2~3배 느렸다. goroutine 을 흉내 내는 비용이 고스란히 붙었으니 당연하다. 여기서 /goal 로 "모든 면에서 최소 2배 빠르게"를 주고 2주를 더 돌렸다.
여기서 나오는 교훈이 하나 있다. JS → Rust 직행은 지금 모델로도 어렵지만, Microsoft 팀이 사람 손으로 JS → Go 를 해둔 덕분에 Go → Rust 는 "비교적 사소한" 작업이 됐다. 그러니 "MS 는 괜히 Go 로 포팅했다, AI 를 기다렸으면 됐다"는 말은 틀리다 — 그 Go 포팅이 없었으면 이것도 없었다.
호환성은 사실상 100% 다. 지금까지 열린 이슈 6개 중 TS Rust 고유 문제는 1개, 나머지 5개는 TSC 7 자체에 있는 버그였다. 버그까지 충실하게 포팅한 것이다.
$420k 의 실체
제목의 42만 달러는 Codex 로 실패한 40만 + Opus 로 성공한 2만(정확히는 약 2.4만)이다. 의미 있는 건 Opus 쪽뿐이고, 그것도 API 정가 기준이다. Theo 는 구독으로 돌렸고, 로그로 환산하면 한 계정 주간 한도의 925~983% — 구독 기준으로 대략 500달러어치라고 계산한다. 500달러에 TSGO 보다 2배 빠르고 메모리를 덜 먹는 TypeScript 를 얻었으면 남는 장사라는 얘기다.
성능 — 그런데 성능이 목적이 아니었다
Theo 가 밝힌 수치는 이렇다.
| 비교 대상 | TS Rust 의 속도 |
|---|---|
| TSC 6 (마지막 JS 버전) | 약 12.5배, 프로젝트에 따라 13~20배 |
| TSGO (TSC 7) | 약 2배 |
bun check (Bun 의 Rust 체커) | 순수 체크는 bun 이 더 빠름 |
bun check 가 더 빠른데도 Theo 가 자기 것을 쓰는 이유는 정확도다. bun 은 Sentry, tRPC 코드베이스에서 잘못된 에러를 냈고 Effect 저장소는 통과하지 못했다고 한다. 또 T3 Code 는 Effect 의 TS 패치(추가 진단)에 의존하는데, TS Rust 는 그걸 내장했기 때문에 "bun 체크 + Effect 체크"를 따로 돌리는 것보다 끝까지 4배쯤 빠르다. 그러면서도 "유지보수 신뢰도로 보면 대부분은 bun 을 추천한다"고 솔직하게 덧붙인다.
그리고 반전 — 성능 때문에 만든 게 아니다.
진짜 이유 — 개발 루프 전체를 V8 isolate 안에
추론은 싸지고, VM 은 비싸진다
Theo 의 논리는 비용 곡선 두 개에서 출발한다.
- 같은 지능 수준의 추론 비용은 1년에 10배 이상 떨어진다(Artificial Analysis 의 cost efficiency 차트 기준)
- 에이전트가 코드를 돌리는 VM 비용은 AI 가 RAM 수요를 빨아들이면서 매년 25~30% 오른다
지금은 Cursor 클라우드처럼 스레드마다 16~32GB VM 을 공짜로 붙여줘도 추론 비용에 비하면 반올림 오차다. 하지만 곧 추론이 VM 보다 싸지는 시점이 온다. 그때 병목은 에이전트가 일하는 컴퓨터다. 에이전트는 진짜 bash, 진짜 파일 시스템이 있는 리눅스 박스를 전제로 학습됐고, 샌드박스를 강화할수록 자원은 더 든다.
VM 대신 isolate
해답으로 꺼낸 게 Cloudflare 다. Cloudflare Workers 는 앱마다 리눅스를 띄우지 않는다. 요청이 오면 V8 isolate 하나에 코드를 올려 실행하고 버린다. 내 코드와 네 코드가 같은 리눅스 위, V8 레벨에서 갈라진다.
VPS / Docker Cloudflare Workers
────────────── ──────────────────
App App App isolate isolate isolate
OS OS OS ───────── V8 ─────────
──── Docker shim ──── OS
OS Hardware
Hardware
Postgres Docker 컨테이너 하나와 Chrome 탭 하나 중 뭐가 자원을 더 먹는지 생각해 보면 차이가 바로 보인다. CPU 도 다르다. VM 은 놀고 있어도 vCPU 를 점유하지만, isolate 는 이벤트 루프를 공유하니 추론 토큰을 기다리는 동안은 CPU 비용이 0 이다. 몇 시간짜리 에이전트 작업도 대부분은 대기 시간이다.
문제는 isolate 가 "Chrome 탭이 못 하는 건 못 한다"는 것이다. 파일 시스템도 없고 네이티브 코드도 못 돌린다. 코드를 올려둘 곳이지 빌드할 곳이 아니다.
빠진 조각이 TypeScript 였다
파일 시스템 쪽은 Vercel 의 Malte Ubl 이 만든 just-bash 가 메운다. 메모리 위에 가짜 파일 시스템과 프로세스를 두고 에이전트에게 진짜 bash 인 것처럼 속이는 라이브러리다. 남은 건 컴파일과 타입 체크 — 에이전트가 "내 코드가 틀렸다"는 피드백을 받을 수단이다.
여기서 GC 얘기가 다시 돌아온다. Go 앱을 WASM 으로 묶으려면 개발자가 쓴 코드뿐 아니라 GC 런타임까지 같이 묶어야 한다. 번들이 커지고 성능도 이상해진다 — esbuild 가 오랫동안 WASM 에서 고생한 이유이고, TSGO 로 넘어오면서 "JS 라서 브라우저든 isolate 든 어디서나 돌던" TypeScript 의 장점을 잃은 이유다. WASM 은 Go 에게는 나쁜 타깃이고, Rust 에게는 최고의 타깃이다.
Theo 의 데모는 GPT 계열 모델이 just-bash + TS Rust 위에서 앱 하나를 통째로 만드는 것이다. 에이전트, 에이전트의 작업 환경, 만들어진 앱, 타입 체크와 컴파일까지 전부 isolate 하나에서 돌았고 RAM 260MB 미만, CPU 피크 4% 였다. 서버의 파일 시스템을 읽기 전용으로 바꿔도 그대로 돈다 — 아무것도 RAM 과 V8 을 벗어나지 않으니까. 같은 데모를 esbuild(Go)로 묶은 버전은 놀고 있을 때도 RAM 을 2배 썼다고 한다.
브라우저 안에서 tsserver 를 돌려 타입 진단을 띄우는 건 나도 PegCode 를 짤 때 Monaco 의 TS worker 로 해봤고, WASM 번들 크기에 발목 잡힌 건 ffmpeg 를 브라우저에서 돌릴 때 겪었다. 그래서 "타입 체커가 isolate 에 들어가는 게 마지막 조각"이라는 말이 꽤 와닿는다.
프롬프트가 아니라 환경이었다
Theo 가 공개한 프롬프트는 허무할 만큼 짧다. "잘했다. 네 판단을 전적으로 믿는다. 호환성과 성능을 계속 개선해라", "TSGO 와 100% 호환에 최대한 가깝게 + 성능 개선, 서브에이전트를 병렬로 계속 돌려라", 그리고 마지막에 "목표는 Go 빌드보다 최소 2배 빠르게"가 전부다. 마지막 목표를 바꾼 이유도 현실적이다 — 호환성을 다 맞추고 나면 성능 개선 하나 해놓고 "끝났다"며 멈췄기 때문이다.
실제로 Theo 가 한 일은 프롬프트가 아니라 환경 손질이었다. systemd 를 죽일 만큼 메모리가 터지는 걸 OS 레벨에서 막고, 컴퓨트가 모자라자 다른 VPS 들에 SSH 접근을 열어주고, 다른 스레드에서 병목과 반복되는 실패 패턴을 계속 감사했다. 본인 표현으로 "매니저로 일할 때와 같은 에너지" — 참호에서 코드를 쓰는 게 아니라 팀이 막히는 곳을 치워주는 일이다.
정리
- TS → JS 변환은 타입 표기를 지우는 쉬운 일이고, 비싼 건 타입 체크다. Microsoft 는 GC 비용이 긴 작업에서는 묻힌다는 점을 근거로 Go 를 골랐다
- Opus 5.5 는 JS 가 아니라 Microsoft 의 Go 포팅을 Go 표준 라이브러리째 Rust 로 옮겼다. 결과는 TSGO 대비 약 2배 빠르고, TSC 7 의 버그까지 그대로인 드롭인 대체품이다
- 진짜 목적은 성능이 아니라 GC 없는 WASM 이다. TS Rust 로 타입 체크까지 V8 isolate 에 들어가면, 에이전트의 개발 루프 전체를 VM 없이 Cloudflare Workers 같은 곳에서 돌릴 수 있다
- 추론이 VM 보다 싸지는 시점이 오면 병목은 에이전트가 일하는 컴퓨터다 — 그리고 이번 작업에서 사람이 한 일은 프롬프트보다 그 환경을 다듬는 쪽이었다
참고 자료
- A 10x Faster TypeScript — TypeScript 팀의 Go 포팅 발표
- microsoft/typescript-go
- How Workers works — Cloudflare 의 isolate 모델
- vercel-labs/just-bash

