버셀이 자바스크립트 엔진 없는 TypeScript 컴파일러를 냈습니다 — TS는 '진짜 언어'가 되는 걸까요
TypeScript는 지난 10년간 웹 개발의 기본값이 됐습니다. 그런데 아무리 타입을 촘촘하게 써도 결국 마지막에는 타입이 다 지워진 채 자바스크립트로 변환되고, V8 같은 엔진 위에서 돌아갑니다. Vercel이 내놓은 Scriptc는 이 마지막 단계를 아예 건너뛰겠다는 시도입니다. TypeScript 코드를 자바스크립트 엔진 없이 곧바로 네이티브 실행 파일로 뽑아냅니다.
먼저 하나 짚고 갑니다. 이 주제로 최근 30일간의 커뮤니티 반응을 훑어봤는데, 레딧에서 유의미한 토론 스레드가 잡히지 않았습니다. 개발자 커뮤니티 전반으로 퍼진 화제라기보다 아직 초기 단계 프로젝트라는 뜻입니다. 그래서 이 글은 커뮤니티 여론 정리보다 “이 접근이 기술적으로 무엇을 뜻하는가"에 무게를 둡니다.
TypeScript는 지금까지 ‘언어’가 아니었습니다
좀 과격하게 들리겠지만 엄밀히 따지면 사실입니다. TypeScript의 공식 포지션은 자바스크립트의 상위집합(superset)이고, 컴파일러가 하는 일은 두 가지뿐입니다. 타입을 검사하고, 그다음 타입을 전부 지웁니다. 이걸 타입 소거(type erasure)라고 부릅니다.
number라고 선언한 변수가 런타임에 실제로 숫자인지는 아무도 보장하지 않습니다. 외부 API에서 문자열이 넘어오면 그냥 문자열이 들어앉습니다. 타입은 개발자와 에디터를 위한 주석에 가깝고, 실행되는 순간에는 존재하지 않습니다.
이 설계에는 분명한 장점이 있었습니다. 기존 자바스크립트 생태계를 통째로 물려받을 수 있었으니까요. npm의 수백만 패키지를 그대로 쓰는 대가로, TypeScript는 독립된 언어가 되기를 포기했습니다.
Scriptc가 건드리는 지점
발상은 간단합니다. 타입 정보를 지우지 말고 코드 생성의 재료로 쓰자는 겁니다.
컴파일러가 number가 64비트 부동소수점이라는 걸 확실히 안다면, 런타임에 “이게 숫자인가 객체인가” 확인할 이유가 없습니다. 객체의 프로퍼티 구조를 미리 안다면 해시맵 조회 대신 고정 오프셋으로 메모리에 직접 접근할 수 있습니다. V8이 JIT 컴파일과 히든 클래스, 인라인 캐시라는 정교한 기법으로 실행 중에 힘들게 알아내는 정보를, AOT(Ahead-Of-Time) 컴파일러는 빌드 시점에 이미 쥐고 있습니다.
결과물은 자바스크립트 파일이 아니라 실행 가능한 바이너리입니다. Node.js도 V8도 없이 그냥 돌아갑니다. 이게 왜 매력적이냐면요.
진짜 노림수는 서버리스 콜드 스타트입니다
Vercel이 이걸 만들었다는 사실 자체가 힌트입니다. Vercel은 서버리스 플랫폼 회사고, 서버리스의 고질병은 콜드 스타트입니다.
요청이 들어오면 컨테이너를 띄우고, Node.js 런타임을 부팅하고, 자바스크립트 번들을 파싱하고, JIT이 워밍업될 때까지 기다립니다. 이 과정이 수백 밀리초씩 잡아먹습니다. 트래픽이 뜸한 함수일수록 매번 이 비용을 냅니다.
네이티브 바이너리는 이 계단을 통째로 없앱니다. 런타임 부팅도, 파싱도, JIT 워밍업도 없습니다. Go나 Rust로 짠 서버리스 함수가 빠른 이유와 정확히 같습니다. 메모리 사용량도 줄어드는데, 서버리스 과금은 대개 메모리 x 실행시간이라 그대로 비용이 줄어듭니다.
Vercel의 계산은 이렇습니다. “우리 고객들은 이미 TypeScript를 쓴다. 언어를 바꾸라고 설득하는 대신, 같은 코드에서 Rust급 실행 특성을 뽑아내자.”
그런데 npm 생태계는 어떻게 하죠
여기가 가장 큰 벽입니다.
자바스크립트에는 정적 컴파일과 상극인 기능이 잔뜩 있습니다. eval, 동적 import(), 프로토타입 체인 런타임 조작, Proxy, with 문 같은 것들입니다. 이 기능들은 “무슨 코드가 실행될지 실행 전에는 알 수 없다"는 전제를 깔고 있는데, AOT 컴파일러는 정확히 그 반대를 요구합니다.
문제는 npm 패키지 상당수가 이런 동적 기능에 기대고 있다는 점입니다. ORM, 의존성 주입 프레임워크, 각종 번들러 플러그인이 대표적입니다. 그래서 이런 프로젝트는 대부분 TypeScript의 부분집합만 지원하는 쪽으로 갑니다. AssemblyScript(TS 문법을 WebAssembly로 컴파일)나 Static TypeScript(MakeCode에서 쓰는 임베디드용 TS 컴파일러) 같은 선행 사례가 모두 그 길을 걸었습니다.
여기서 딜레마가 생깁니다. 지원 범위를 좁히면 기존 코드를 못 쓰고, 넓히면 성능 이점이 사라집니다. Scriptc가 어디에 선을 긋느냐가 성패를 가를 겁니다.
그래도 흐름 자체는 분명합니다
Scriptc 하나만 보면 실험적 프로젝트지만, 주변을 보면 방향이 읽힙니다.
Microsoft는 2025년에 TypeScript 컴파일러 자체를 Go로 다시 작성해 10배 빠른 빌드를 내놨습니다. 프론트엔드 툴체인은 Rust(SWC, Turbopack, Oxc)와 Go(esbuild)로 갈아타는 중이고, Bun과 Deno는 런타임 레이어에서 Node.js의 오버헤드를 걷어내고 있습니다.
공통점은 하나입니다. 자바스크립트로 자바스크립트 도구를 만들던 시대가 끝나가고 있다는 것. Scriptc는 그 흐름을 언어 실행 자체로까지 밀고 나간 버전입니다.
물론 웹 브라우저에서는 여전히 자바스크립트가 유일한 실행 환경입니다. 이런 시도가 의미 있는 곳은 서버와 엣지, CLI 도구 쪽입니다. 프론트엔드가 통째로 네이티브로 바뀌는 그림은 아닙니다.
마무리
TypeScript가 “진짜 언어"가 되느냐는 질문의 답은 아마 절반쯤 그렇다입니다. 언어 명세가 자바스크립트에서 독립하는 일은 없을 겁니다. 대신 같은 TypeScript 코드가 상황에 따라 브라우저용 JS로도, 서버용 네이티브 바이너리로도 컴파일되는 다중 백엔드 구조로 갈 가능성이 큽니다. C 코드가 x86으로도 ARM으로도 컴파일되는 것과 비슷합니다.
다만 아직은 실험 단계입니다. 실제 벤치마크와 npm 호환 범위가 나오기 전까지는 판단하기 이릅니다. 익숙한 TypeScript 문법을 그대로 쓰는 대신 라이브러리 선택지가 줄어드는 거래라면, 받아들이시겠습니까?
댓글
댓글을 불러오는 중...