TypeScript 7.0 발표

1 hour ago 1
  • TypeScript 7.0은 도구체인을 Go 기반 네이티브 코드로 이식한 릴리스로, 대형 프로젝트의 전체 빌드에서 보통 8~12배 속도 향상을 제공함
  • 새 tsc는 기존처럼 npm의 typescript 패키지로 설치하며, 편집기 지원은 LSP 기반 언어 서버로 VS Code, Visual Studio, WebStorm 등에서 동작함
  • vscode, sentry, bluesky, playwright, tldraw 같은 코드베이스에서 빌드 시간이 크게 줄었고, 일부 환경에서는 총 메모리 사용량도 낮아짐
  • TypeScript 7.0은 아직 안정적인 프로그래밍 API가 없어 typescript-eslint, Vue, MDX, Astro, Svelte, Angular 템플릿 타입 검사 등 TypeScript를 내장하는 도구는 TypeScript 6.0 병행이 필요함
  • 새 기본값과 제거된 옵션이 있어 TypeScript 6.0 변경 사항을 먼저 적용하는 편이 전환에 유리하며, TypeScript 7.1에서 새 API 제공이 예정됨

Go 기반 네이티브 TypeScript

  • TypeScript 7.0은 TypeScript 도구체인의 네이티브 포트로, Go로 작성된 새 코드베이스를 사용함
  • 기존 코드베이스의 구조와 로직을 최대한 유지해 두 컴파일러 간 결과의 일관성과 호환성을 맞추는 방향으로 포팅됨
  • 새 코드베이스는 네이티브 코드 속도, 공유 메모리 기반 멀티스레딩, 여러 최적화를 통해 전체 빌드에서 보통 8~12배 빠른 결과를 냄
  • 설치는 기존처럼 npm으로 가능함
npm install -D typescript
  • 설치 후 워크스페이스에서 새 tsc 실행 파일을 사용할 수 있으며, npx tsc로 실행 가능함

개발 피드백 루프 단축

  • TypeScript는 편집기 로딩, 전체 참조 찾기, 자동 완성, 진단, tsc, --watch 모드 등 개발 과정 여러 단계에 관여함
  • TypeScript 7은 이 과정 전반의 대기 시간을 줄여 피드백 루프를 짧게 만듦
  • VS Code 코드베이스에서 오류가 있는 파일을 열었을 때 첫 오류가 보이기까지 걸리는 시간은 약 17.5초에서 1.3초 미만으로 줄어 13배 이상 빨라짐
  • 편집기 지원은 LSP 기반이며, 새 언어 서버는 멀티스레딩을 활용해 동시 요청을 빠르게 처리함
  • VS Code 사용자는 TypeScript 7 전용 확장을 설치할 수 있고, 향후 몇 주 안에 VS Code 자체에도 TypeScript 7 지원이 포함될 예정임
  • Visual Studio 최신 버전은 워크스페이스에 따라 TypeScript 7을 자동 활성화함

빌드 성능과 메모리 결과

  • TypeScript 6과 7을 대형 오픈소스 코드베이스에서 비교한 전체 빌드 시간은 다음과 같음
코드베이스 TypeScript 6 TypeScript 7 속도 향상
vscode 125.7초 10.6초 11.9배
sentry 139.8초 15.7초 8.9배
bluesky 24.3초 2.8초 8.7배
playwright 12.8초 1.47초 8.7배
tldraw 11.2초 1.46초 7.7배
  • 같은 빌드에서 TypeScript 7은 대체로 총 메모리 사용량도 더 낮았음
코드베이스 TypeScript 6 TypeScript 7 메모리 변화
vscode 5.2GB 4.2GB -18%
sentry 4.9GB 4.6GB -6%
bluesky 1.8GB 1.3GB -26%
playwright 1.0GB 0.9GB -11%
tldraw 0.6GB 0.5GB -15%

실제 코드베이스 검증과 팀 피드백

  • TypeScript 프로젝트는 10년 이상 누적된 수만 개 테스트를 모든 main 브랜치 커밋에서 실행함
  • TypeScript 7은 이 테스트 외에도 내부·외부 대형 팀의 실제 코드베이스에서 검증됨
  • Microsoft 내부에서는 Loop, Office, PowerBI, Teams, Xbox 팀이 TypeScript 7을 검증함
  • 외부에서는 Bloomberg, Canva, Figma, Google, Lattice, Linear, Miro, Notion, Sentry, Slack, Vanta, Vercel, VoidZero 등이 코드베이스에서 테스트하고 피드백을 제공함
  • 새 언어 서버는 TypeScript 6.0 대비 실패한 언어 서버 명령을 80% 이상, 서버 크래시를 60% 이상 줄임
  • 실제 팀 피드백에는 다음 사례가 포함됨
    • Slack은 TypeScript 7로 merge queue 시간이 40% 줄었고, CI 타입 검사 시간이 약 7.5분에서 1.25분으로 낮아졌다고 전함
    • Vanta는 큰 프로젝트 중 하나에서 최대 9배 빌드 속도 향상을 보임
    • Microsoft News Services 팀은 CI 빌드 대기 시간을 월 400시간 절감함
    • Canva는 편집기에서 첫 오류가 보이기까지 걸리는 시간이 약 58초에서 4.8초로 줄었다고 전함

TypeScript 6.0과 병행 실행

  • TypeScript 7.0은 아직 API를 포함하지 않음
  • TypeScript 7.1에서 새롭고 다른 API를 제공할 예정임
  • 그 전까지 컴파일러에 대한 프로그래밍 접근이 필요한 도구를 위해 TypeScript 6.0과 7.0을 병행 실행할 수 있음
  • 새 호환성 패키지 @typescript/typescript6는 tsc6 실행 파일을 제공하고 TypeScript 6.0 API를 다시 내보냄
  • typescript-eslint처럼 peer dependency로 typescript를 직접 import하는 도구에는 npm alias 사용을 권장함
npm install -D typescript@npm:@typescript/typescript6
  • TypeScript 6 API와 TypeScript 7의 tsc를 함께 쓰려면 다음처럼 alias를 둘 수 있음
{ "devDependencies": { "@typescript/native": "npm:typescript@^7.0.2", "typescript": "npm:@typescript/typescript6@^6.0.2" } }
  • 기존 @typescript/native-preview 패키지는 TypeScript 7 새 코드베이스의 nightly 빌드를 제공해 왔고, 주간 다운로드가 850만 회 이상이었음
  • 앞으로 nightly 빌드는 표준 typescript 패키지의 next 태그로 재개될 예정임
npm install -D typescript@next

병렬화 제어 옵션

  • TypeScript 7.0은 파싱, 타입 검사, emit 등 여러 단계를 병렬 실행

  • 파싱과 emit은 파일별로 독립 실행이 쉬워 큰 코드베이스에서 비교적 적은 오버헤드로 확장됨

  • 새 실험적 플래그 --checkers, --builders, --singleThreaded가 병렬화 동작을 조정함

  • --checkers

    • TypeScript 7.0은 고정된 수의 타입 검사 워커를 만들고, 같은 입력 파일에 대해 항상 동일하게 작업을 나눠 동일한 결과를 내도록 함
    • 기본 타입 검사 워커 수는 4개이며, --checkers로 조정 가능함
    • --checkers 8을 사용한 같은 머신의 결과는 다음과 같음
    코드베이스 TypeScript 6 TypeScript 7 --checkers 8 속도 향상
    vscode 125.7초 7.51초 16.7배
    sentry 139.8초 12.08초 11.6배
    bluesky 24.3초 2.01초 12.1배
    playwright 12.8초 1.16초 11배
    tldraw 11.2초 1.06초 10.6배
    • --checkers를 늘리면 더 많은 CPU 코어를 활용해 빌드가 빨라질 수 있지만, 보통 메모리 사용량 증가가 따름
    • CPU 코어와 메모리가 적은 CI runner에서는 값을 낮춰 불필요한 오버헤드를 피할 수 있음
    • --checkers 1은 타입 검사를 사실상 단일 스레드로 만들고 중복 작업을 제거함
    • 드문 경우 --checkers 수 변화가 순서 의존 결과를 드러낼 수 있어, 빌드 환경 전반에서 고정된 checker 수를 지정하는 방식이 도움이 될 수 있음
  • --builders

    • --builders는 --build 실행 시 동시에 실행할 수 있는 프로젝트 참조 빌더 수를 제어함
    • 프로젝트가 많은 monorepo에서 특히 도움이 될 수 있음
    • 값을 늘리면 빌드가 빨라질 수 있지만 메모리 사용량도 증가할 수 있음
    • --checkers와 곱셈 효과가 있어 --checkers 4 --builders 4는 최대 16개 타입 검사기가 동시에 실행될 수 있음
    • --builders 수 변화는 --checkers와 달리 다른 결과를 만들지 않아야 함
    • 프로젝트 참조 빌드는 기본적으로 프로젝트 의존성 그래프에 의해 병목이 생김
  • --singleThreaded

    • --singleThreaded는 컴파일러 전체를 단일 스레드로 실행하게 함
    • 디버깅, TypeScript 6과 7의 성능 비교, 외부 병렬 빌드 오케스트레이션, 리소스가 매우 제한된 환경에서 유용할 수 있음
    • 이 플래그는 타입 검사 워커 수를 1로 제한할 뿐 아니라 파싱과 emit도 단일 스레드에서 수행하게 함

새 --watch 모드

  • TypeScript 7은 --watch 모드를 완전히 다시 만들었음
  • 새 --watch는 Parcel bundler의 file-watcher를 기반으로 효율적이고 안정적인 크로스플랫폼 파일 감시 기능을 제공함
  • Go 표준 라이브러리에는 내장 파일 감시 API가 없고, 검토한 서드파티 라이브러리들은 안정성, 성능, 크로스플랫폼 지원, 빌드 도구 통합에서 문제가 있었음
  • 순수 polling 방식은 여러 운영체제에서 동작했지만, node_modules 의존성이 많은 대형 프로젝트에서는 계산 비용이 컸음
  • TypeScript 팀은 VS Code에서 쓰여 온 @parcel/watcher를 Go로 포팅했고, C++ 툴체인 의존성을 피하기 위해 최소한의 어셈블리 shim을 사용함
  • 이 watcher는 독립 패키지이며, TypeScript 7의 --watch 모드에서 플랫폼 전반의 리소스 사용 개선을 가져옴

TypeScript 6.0 기본값과 호환성 변화

  • TypeScript 7.0은 TypeScript 6.0의 타입 검사와 명령줄 동작과 호환되도록 만들어짐
  • stableTypeOrdering 플래그가 켜져 있고 ignoreDeprecations가 설정되지 않은 상태에서 TypeScript 6.0으로 깨끗하게 컴파일되는 코드는 TypeScript 7.0에서도 동일하게 컴파일되어야 함
  • TypeScript 7.0은 TypeScript 6.0의 새 기본값을 채택하고, TypeScript 6.0에서 deprecated된 플래그와 구문에는 hard error를 냄
  • 주요 설정 기본값 변화는 다음과 같음
    • strict 기본값은 true
    • module 기본값은 esnext
    • target 기본값은 esnext 직전의 현재 안정 ECMAScript 버전
    • noUncheckedSideEffectImports 기본값은 true
    • libReplacement 기본값은 false
    • stableTypeOrdering 기본값은 true이며 끌 수 없음
    • rootDir 기본값은 ./
    • types 기본값은 []이며, 이전 동작은 ["*"]로 복원 가능함
  • rootDir과 types 변화가 가장 놀라울 수 있는 변경으로 꼽힘
    • tsconfig.json이 src 같은 소스 디렉터리 밖에 있는 프로젝트는 기존 디렉터리 구조 유지를 위해 rootDir을 명시해야 함
    • 특정 전역 선언에 의존하는 프로젝트는 필요한 @types 패키지를 types에 명시해야 함
{ "compilerOptions": { "rootDir": "./src" }, "include": ["./src"] } { "compilerOptions": { "types": ["node", "jest"] } }

제거되거나 hard error가 된 동작

  • TypeScript 7.0에서는 TypeScript 6.0에서 deprecated된 여러 옵션과 구문이 더 이상 지원되지 않음
  • 주요 항목은 다음과 같음
    • target: es5 미지원
    • downlevelIteration 미지원
    • moduleResolution: node/node10 미지원, nodenext와 bundler 권장
    • module: amd, umd, systemjs, none 미지원, bundler 또는 브라우저 기반 모듈 해석과 함께 esnext나 preserve 권장
    • baseUrl 미지원, paths는 baseUrl 대신 프로젝트 루트 기준 상대 경로로 업데이트 가능함
    • moduleResolution: classic 미지원, bundler 또는 nodenext 권장
    • esModuleInterop과 allowSyntheticDefaultImports는 false로 설정할 수 없음
    • alwaysStrict는 true로 간주되며 false로 설정할 수 없음
    • namespace 선언에서 module 키워드 사용 불가
    • import에서 asserts 키워드 사용 불가, ECMAScript import attribute 문법 변화에 맞춰 with 사용 필요
    • skipDefaultLibCheck 아래에서 /// <reference no-default-lib /> 지시문은 더 이상 존중되지 않음
    • 현재 디렉터리에 tsconfig.json이 있으면 명령줄 빌드에서 파일 경로를 받을 수 없고, 명시적 --ignoreConfig가 필요함

템플릿 리터럴 타입과 JavaScript 지원 변화

  • TypeScript 7.0은 템플릿 리터럴 타입 추론에서 Unicode code point를 더 자연스럽게 처리함
type HeadTail<S> = S extends `${infer Head}${infer Tail}` ? [Head, Tail] : never; type Result = HeadTail<"😀abc">; // 7.0: ["😀", "abc"] // 이전: ["\ud83d", "\ude00abc"]
  • 이전에는 JavaScript의 UTF-16 indexing 동작을 따라 "😀"를 surrogate pair의 두 부분으로 나눴음
  • 새 동작은 for...of나 [...str]처럼 "😀"를 하나의 단위로 다루는 직관에 맞음
  • UTF-16 code unit을 의도적으로 모델링한 타입 수준 문자열 조작에는 breaking change가 될 수 있음
  • JavaScript 지원은 TypeScript 파일 분석 방식과 더 일관되도록 재작업됨
    • 타입 위치에서 값을 사용할 수 없고 typeof someValue를 써야 함
    • @enum은 더 이상 특별 취급되지 않음
    • 단독 ?는 타입으로 사용할 수 없고 any를 써야 함
    • @class는 함수를 생성자로 만들지 않으며 class 선언을 써야 함
    • postfix !는 지원되지 않음
    • 타입 이름은 @typedef 태그 안에서 정의해야 함
    • Closure 스타일 함수 문법은 더 이상 지원되지 않고 TypeScript 축약 문법을 써야 함
  • this aliasing과 함수 prototype 전체 재할당 같은 일부 JavaScript 패턴도 더 이상 특별 취급되지 않음
  • TypeScript 6.0과 7.0의 차이는 CHANGES.md에 더 자세히 정리되고 있음

편집기 기능과 제한

  • TypeScript 7.0에는 beta 이후 누락됐던 여러 편집기 기능이 추가됨
  • 자동 import, 확장 가능한 hover, inlay hint, code lens, go-to-source-definition, JSX linked editing, tag completion 등이 포함됨
  • semantic highlighting, “sort imports”, “remove unused imports” 등 TypeScript 7.0 beta에서 빠졌던 기능도 들어옴
  • 언어 서버 품질을 위해 테스트와 진단 인프라를 재구축했고, GitHub의 주요 TypeScript·JavaScript 코드베이스를 대상으로 fuzz test를 수행할 수 있음

내장 언어 워크플로의 현재 제약

  • Vue, MDX, Astro, Svelte 등을 사용하는 워크플로는 아직 TypeScript 7을 활용하지 못할 가능성이 높음
  • Angular 템플릿 같은 특수 템플릿 타입 검사도 TypeScript 7을 사용하지 못할 가능성이 높음
  • 주된 이유는 TypeScript 7이 아직 안정적인 프로그래밍 API를 노출하지 않기 때문임
  • Volar처럼 TypeScript를 자체 컴파일러와 언어 서비스에 내장하는 도구는 현재 TypeScript 6.0에 의존할 수밖에 없음
  • TypeScript 팀은 이 문제를 특정 시점의 제약으로 보고, 해당 프로젝트 유지관리자들과 협력해 TypeScript 7 지원을 확보할 계획임
  • 그 전까지는 language server plugin이 필요 없는 시나리오에서 TypeScript 7 사용을 권장함
  • Angular 프로젝트는 CLI에서 빠른 프로젝트 전체 오류 감지를 위해 TypeScript 7의 tsc를 쓰고, 편집기 지원에는 TypeScript 6.0을 함께 사용할 수 있음
  • Vue, MDX, Astro, Svelte 등은 당분간 TypeScript 6.0을 계속 사용해야 함
  • VS Code에서는 “Disable TypeScript 7 Language Server” 명령으로 TypeScript 6.0으로 되돌릴 수 있음

향후 계획

  • TypeScript 7.0 출시는 TypeScript 프로젝트에서 1년 이상 주력한 네이티브 포트의 주요 마일스톤임
  • 7.0 이후에는 새 기능 작업, 사용성 개선, 추가 성능 개선, 생태계를 위한 새 API 구현으로 돌아갈 예정임
  • TypeScript 7.0 이전과 비슷하게 3~4개월마다 새 기능 릴리스를 낼 것으로 예상함
  • TypeScript 7.1은 커뮤니티 전환을 돕기 위한 격차 해소와 새 API 제공이 예정되어 있음
Read Entire Article