TypeScript 컴파일러, Go 언어로 갈아탄다고요?! 속사정 한번 알아볼까요?
최근에 TypeScript (타입스크립트) 컴파일러와 도구를 Go (고) 언어로 새롭게 개발하고 있다는 소식, 혹시 들어보셨나요?
이번 네이티브 버전으로 에디터 실행 속도가 엄청나게 빨라지고, 빌드 시간도 무려 10배나 단축될 거라고 하는데요.
메모리 사용량까지 줄어든다고 하니 정말 기대되지 않으세요?
이번 블로그 글에서는 이 소식에 숨겨진 자세한 이야기를 한번 풀어볼까 합니다.
- 코드 기반: JavaScript (자바스크립트) vs. 네이티브
혼란을 막기 위해 몇 가지 용어를 먼저 정리하고 넘어갈게요.
- JavaScript (자바스크립트) 코드 기반: 현재 TypeScript (타입스크립트)의 코드 기반을 말합니다. 놀랍게도 TypeScript (타입스크립트)로 작성되어 있습니다.
- 네이티브 코드 기반: 이번에 새로 개발되는 코드 기반입니다. TypeScript (타입스크립트) 팀에서 "네이티브"라는 용어를 사용하고 있어서 저도 그대로 사용할게요. Go (고) 언어로 작성되었습니다.
- 왜 이렇게 난리일까요?
타입 검사는 외부 도구가 대신 해줄 수 없는 TypeScript (타입스크립트) 컴파일러의 핵심 기능인데요.
.js
파일 생성 속도는 이미 빨라졌습니다. 네이티브 도구와 타입 제거 기술 덕분이죠..d.ts
파일 생성 속도도 이미 빨라졌습니다. 네이티브 도구와 분리된 선언 기술 덕분이고요.
그런데 이번에는 타입 검사까지 빨라진다고 하니, 정말 엄청난 소식이 아닐 수 없습니다.
- 앞으로의 일정은 어떻게 될까요?
현재 최신 버전의 TypeScript (타입스크립트)는 5.8 버전입니다.
- TypeScript 6 (JavaScript (자바스크립트)): 기존 JavaScript (자바스크립트) 코드 기반은 6.x 버전 시리즈까지 계속 사용될 예정입니다. 6.0 버전에서는 네이티브 코드 기반과의 호환성을 맞추기 위해 몇 가지 호환성이 깨지는 변경 사항이 있을 거라고 합니다.
- TypeScript (타입스크립트)의 원래 코드 이름: 스트라다 (Strada)
- TypeScript 7 (네이티브): 네이티브 코드 기반이 JavaScript (자바스크립트) 코드 기반과 거의 동등한 수준에 도달하면, TypeScript (타입스크립트) 7.0 버전으로 출시될 예정입니다.
- 네이티브 코드 기반의 코드 이름: 코르사 (Corsa)
앞으로 오랫동안 두 코드 기반이 함께 사용될 거라고 하네요.
- 어떤 부분을 마이그레이션해야 할까요?
이번 마이그레이션에 어떤 부분들이 포함되는지 알아두면 좋을 것 같습니다.
- 명령줄 TypeScript (타입스크립트) 컴파일러
- TypeScript (타입스크립트) 언어 서버 (에디터가 TypeScript (타입스크립트)를 지원하도록 돕는 역할)
기존 JavaScript (자바스크립트) 코드 기반은 널리 사용되는 Language Server Protocol (랭귀지 서버 프로토콜)보다 먼저 개발되었고, Language Server Protocol (랭귀지 서버 프로토콜)을 사용하지 않았습니다.
하지만 새로운 언어 서버는 Language Server Protocol (랭귀지 서버 프로토콜)을 사용할 예정이라고 합니다.
이렇게 되면 에디터에서 TypeScript (타입스크립트)를 지원하기가 더 쉬워질 것으로 보입니다.
- TypeScript (타입스크립트) 코드 기반을 사용하는 도구들
Go (고) 코드 기반과 인터페이스하려면 완전히 새로운 접근 방식이 필요합니다.
- 내부 구조가 지금보다 훨씬 적게 외부에 노출될 예정입니다.
- 프로세스 간 통신 방식으로 상호 작용이 이루어집니다.
- 네이티브 버전은 언제쯤 사용할 수 있을까요?
현재 tsc
(TypeScript (타입스크립트) 컴파일러)는 잘 작동하고 있습니다.
아직 네이티브 버전에 없는 기능은 다음과 같습니다.
- JSX (제이에스엑스)
- JSDoc (제이에스닥)을 통한 타입 정의
- 빌드 모드 (프로젝트 참조)
- 2025년 중반: JSX (제이에스엑스)와 JSDoc (제이에스닥)을 지원하는
tsc
(빌드 모드 제외) - 2025년 말: 모든 기능을 갖춘
tsc
와 언어 서버
출처: “A 10x Faster TypeScript (10배 빠른 TypeScript (타입스크립트))”
- 프로젝트는 언제 시작되었을까요?
Anders Hejlsberg (안더스 하일스버그)가 처음 프로토타입을 만든 시점:
- 2024년 8월 시작
- 스캐너와 파서 (parser)를 작성하는 데 1~1.5개월 소요
- 초기 접근 방식: 코드를 직접 수동으로 작성
- 이후: TypeScript (타입스크립트) 코드를 Go (고) 코드로 자동 변환해주는 도구 개발
코드를 변환하는 것은 (약간의 수동 작업이 필요했지만) 꽤 잘 작동했다고 합니다.
하지만 데이터 구조를 변환하는 것은 수동으로만 가능했다고 하는데요.
왜냐하면 JavaScript (자바스크립트) 객체 (유연한 타입)와 Go (고) 구조체 (고정밀 데이터 레이아웃)는 매우 다르기 때문입니다.
게다가 이제는 동시성 환경에서 작동해야 합니다.
예를 들어, JavaScript (자바스크립트) 코드 기반은 타입을 생성할 때 각 타입에 일련번호를 부여해서 타입 순서를 관리합니다.
하지만 Go (고) 코드 기반에서는 여러 스레드가 동시에 실행되기 때문에 타입 생성 순서가 더 이상 일정하지 않아서 기존 접근 방식이 통하지 않게 되었습니다.
- 왜 다른 프로그래밍 언어 대신 Go (고)를 선택했을까요?
TypeScript (타입스크립트) 팀은 새로운 코드 기반을 완전히 새로 작성하는 것보다, 기존 JavaScript (자바스크립트) 코드 기반을 (거의) 그대로 옮겨오고 싶어 했습니다.
이유는 두 가지입니다.
- 새로운 코드 기반은 기존 코드 기반을 (거의) 완벽하게 대체할 수 있어야 합니다. 하지만 완전히 새로 작성하면 이렇게 하기가 어렵습니다.
- 새로 작성하는 것은 시간도 훨씬 오래 걸립니다.
새로운 코드 기반에 사용할 프로그래밍 언어에 대한 요구 사항을 살펴보면, 몇 가지는 기존 코드 기반을 옮겨오기로 결정했기 때문에 생긴 요구 사항입니다.
- 순환 데이터 구조 지원: TypeScript (타입스크립트) 코드 기반에서 순환 데이터 구조를 많이 사용합니다.
- Garbage Collection (가비지 컬렉션): 기존 코드 기반이 Garbage Collection (가비지 컬렉션)을 사용한다고 가정하고 작성되었습니다.
- JavaScript (자바스크립트) 코드 기반의 코딩 스타일: 객체 지향 프로그래밍 (OOP) 스타일보다는 함수형 프로그래밍 스타일에 가깝고, 클래스를 많이 사용하지 않는 스타일입니다. Go (고) 언어는 원래 함수형 프로그래밍 스타일로 코드를 작성하는 데 적합합니다.
나머지 요구 사항들은 성능과 사용 편의성 (개발자 경험)을 고려해서 결정되었습니다.
- 모든 주요 플랫폼에서 네이티브 코드 지원: Windows (윈도우), macOS (맥OS), Linux (리눅스) 등 다양한 환경에서 잘 작동해야 합니다.
- 간단하고 배우기 쉬운 언어: TypeScript (타입스크립트) 개발팀은 물론이고, 더 많은 개발자들이 쉽게 Go (고) 언어를 배우고 기여할 수 있어야 합니다.
- 훌륭한 개발 도구: 디버깅, 프로파일링, 테스트 등 개발에 필요한 도구들이 잘 갖춰져 있어야 합니다.
- 메모리 내 데이터 구조 레이아웃 제어: Go (고) 언어의 구조체를 사용하면 구조체 배열을 단일 할당으로 생성할 수 있습니다. (JavaScript (자바스크립트)에서는 배열 요소를 추가할 때마다 메모리 할당이 발생합니다.) 이렇게 메모리 사용 방식을 최적화해서 성능을 향상시킬 수 있습니다.
- Shared Memory Concurrency (공유 메모리 동시성)에 대한 강력한 지원: 코드 속도를 향상시키는 데 중요한 요소입니다. (자세한 내용은 다음 섹션에서 설명)
- 왜 C# (씨샵)이 아닐까요?
"왜 C# (씨샵)이 아닌 Go (고) 언어를 선택했나요?"
라는 질문에 Anders Hejlsberg (안더스 하일스버그)는 다음과 같이 답변했습니다.
- Go (고) 언어가 C# (씨샵)보다 더 Low-level (저수준) 언어입니다.
- Go (고) 언어가 네이티브 코드 생성 (데이터 구조 레이아웃 지정 포함)에 더 나은 지원을 제공합니다.
- JavaScript (자바스크립트) 코드 기반에서 사용된 비-객체 지향 프로그래밍 (OOP) 코딩 스타일에는 Go (고) 언어가 더 적합합니다.
- 10배나 빨라지는 속도 향상의 비결은 뭘까요?
- 절반의 속도 향상: Shared Memory Concurrency (공유 메모리 동시성)과 멀티 코어 활용 덕분입니다.
- 나머지 절반의 속도 향상: 네이티브 코드 자체의 성능 덕분입니다. JavaScript (자바스크립트)는 Just-In-Time (JIT) 컴파일을 해야 하고, 객체의 유연성을 높이기 위한 여러 가지 처리가 필요하고, 객체를 Inline (인라인)으로 처리할 수 없고 (배열 요소를 할당할 때마다 메모리 할당 발생) 등등 여러 가지 성능상의 제약이 있습니다.
JavaScript (자바스크립트)도 Web Worker (웹 워커)를 통해 동시성을 지원하지만, 메모리 공유는 매우 제한적입니다.
TypeScript (타입스크립트) 컴파일은 다음과 같은 단계로 이루어집니다.
- Parsing (파싱): Abstract Syntax Tree (추상 구문 트리) (AST) 생성
- Binding (바인딩): 선언에 대한 "Symbol Table (심볼 테이블)" 생성, Control Flow Graph (제어 흐름 그래프) 설정 등
- Type Checking (타입 검사)
- Emitting (내보내기): 코드 생성
네이티브 코드 기반에서는 Parsing (파싱)과 Binding (바인딩) 단계를 독립적으로 처리할 수 있습니다.
(메모리 공유 불필요) 이후 생성된 데이터 구조는 Immutable (불변) 데이터 구조이기 때문에 스레드 간에 쉽게 공유할 수 있습니다.
Parsing (파싱), Binding (바인딩), Emitting (내보내기) 단계의 속도는 사용되는 코어 수에 비례해서 선형적으로 증가합니다.
이 세 단계를 합치면 전체 컴파일 시간의 약 1/3을 차지합니다.
Type Checking (타입 검사) 단계는 나머지 2/3를 차지하고, 병렬화하기가 쉽지 않습니다.
그래서 다음과 같은 방법을 사용합니다.
- Type Checking (타입 검사)는 개별 파일 단위로 작동합니다. 필요한 정보가 있으면 Lazy Loading (지연 로딩) 방식으로 가져옵니다.
- 기술: 여러 개의 Type Checker (타입 검사기)를 실행하고, 각 Type Checker (타입 검사기)에게 파일 일부를 할당합니다.
스레드 안전성을 크게 고려할 필요는 없습니다.
Type Checker (타입 검사기)들은 Immutable (불변) AST (추상 구문 트리)만 공유하기 때문입니다.
약간의 중복 작업이 발생하지만, 타입 정보 대부분이 로컬에 있기 때문에 중복 작업으로 인한 성능 저하는 크지 않습니다.
하지만 스레드들이 완전히 독립적으로 작동할 수는 없습니다.
예를 들어, 에러 메시지가 중복되서 표시되지 않도록 하고, 에러 메시지 순서가 일정하게 유지되도록 해야 합니다.
4개의 Type Checker (타입 검사기)를 사용하는 경우 (현재 하드 코딩된 숫자), 메모리 사용량은 20% 정도 증가하지만 (중복 작업 때문에), 타입 검사 속도는 2~3배 빨라집니다.
참고로 여기서 20% 증가는 싱글 Type Checker (타입 검사기) Go (고) 버전을 기준으로 한 것이고, 싱글 Type Checker (타입 검사기) Go (고) 버전은 JavaScript (자바스크립트) 코드 기반보다 메모리를 절반만 사용합니다.
8개의 Type Checker (타입 검사기)를 사용하는 경우, 속도 향상은 20% 정도밖에 추가되지 않았다고 합니다.
- 네이티브 코드 기반이 WebAssembly (웹어셈블리)에서도 실행될까요?
WebAssembly (웹어셈블리) 지원은 온라인 TypeScript (타입스크립트) Playground (플레이그라운드) 같은 Use Case (사용 사례)를 가능하게 하기 때문에 매우 중요합니다.
그리고 실제로 WebAssembly (웹어셈블리)를 지원한다고 합니다.
Kevin Deng (케빈 뎅)은 WebAssembly (웹어셈블리)로 컴파일된 새로운 코드 기반을 사용하는 “TypeScript Go Playground (TypeScript (타입스크립트) Go (고) Playground (플레이그라운드))”를 개발했습니다.
Go (고) 언어의 WebAssembly (웹어셈블리) 결과물 크기와 성능을 개선하는 작업이 계속 진행 중이라고 하니, 앞으로 더 좋아질 것으로 기대됩니다.
관련 GitHub (깃허브) 논의: “Go Wasm performance (Go (고) WebAssembly (웹어셈블리) 성능)”
11. 결론: 정말 놀라운 성과
TypeScript (타입스크립트) 팀이 JavaScript (자바스크립트) 코드 기반을 Go (고) 언어로 이렇게 빨리 옮겨온 것이 정말 놀랍습니다.
위에서 언급한 팟캐스트에서 Hejlsberg (하일스버그)는 "8월에 프로토타입 개발을 시작했다"고 말했는데요.
저는 2024년 8월이 아니라, 2023년 8월이나 그 이전인 줄 알았습니다.
이렇게 빠른 속도는 TypeScript (타입스크립트) 팀의 접근 방식이 얼마나 영리한지 보여주는 증거라고 생각합니다.
만약 기존 JavaScript (자바스크립트) 코드 기반을 그대로 옮겨오는 대신 완전히 새로 작성했다면, 몇 년은 더 걸렸을 것이고, 두 코드 기반 간에 불일치가 많이 발생했을 겁니다.
Anders Hejlsberg (안더스 하일스버그)가 걱정하는 점 중 하나는, 타입 검사 속도가 너무 빨라지면 사람들이 타입 연산량이 많은 타입 (예: Template Literal Types (템플릿 리터럴 타입))을 마구 사용하게 될 수도 있다는 것입니다.
언젠가는 타입 성능을 분석하는 도구가 나오게 될지도 모르겠네요.
타입 레벨 디버깅도 꽤 유용할 것 같고요.
'Javascript' 카테고리의 다른 글
JavaScript 디버깅의 숨겨진 보석: error.cause, 에러의 근본 원인을 쉽게 찾아볼까요? (0) | 2025.03.22 |
---|---|
Node.js Event Loop 속속들이 파헤쳐보기: 싱글 스레드 모델의 비밀, 알아볼까요? (0) | 2025.03.22 |
TypeScript 객체 타입 Union과 Intersection (0) | 2025.03.22 |
타입스크립트(TypeScript) 왜 써야 할까? (0) | 2025.03.22 |
타입스크립트(TypeScript)가 뭔가요? 자바스크립트(JavaScript) 개발자를 위한 간단 소개 (0) | 2025.03.22 |