Transcript
00:00:00TypeScript 7이 공식 출시되었습니다. 1년이 넘는 고된 개발 끝에
00:00:05컴파일러를 Go로 이식하는 과정에서 AI만으로도 전체를 구현할 수 있음이 증명되었죠.
00:00:10개발자들도 아주 기뻐할 겁니다. 이제 `npm install typescript`를 실행하면
00:00:16Go 컴파일러가 포함된 버전 7을 받게 됩니다. 며칠 전 마이크로소프트의
00:00:20발표 영상에 이어, 어떻게 이런 엄청난 성능 향상을
00:00:25이뤄냈는지 파헤쳐 보려 합니다. 결과는 정말 놀랍습니다. 새 컴파일러는
00:00:318천 개 가량의 파일, 130만 줄에 달하는 VS Code 코드베이스를 기존 컴파일러의 125초 대신
00:00:39단 10초 만에 빌드해 냅니다. TypeScript가 GitHub 인기 언어 1위를
00:00:44당당히 차지하고 있는 상황에서, 새 컴파일러는 무수한 삶을 바꿔놓을 것입니다. 생각만 해도 벅차오르네요.
00:00:49버전 6과 7 사이의 거의 동일한 기능들을 훑어보기보다는,
00:00:54어떻게 이런 성능 개선을 달성했는지 명확히 짚어보겠습니다. 새 컴파일러를 살펴보고
00:00:59무엇이 이토록 빠르게 만드는지 살펴보겠습니다. 왜 재작성했을까요? C#의 창시자이자 마이크로소프트 테크니컬 펠로우인
00:01:09C#의 창시자이자 MS 테크니컬 펠로우인 아놀드 하일스버그는 아주 솔직하게 말했습니다. JavaScript는 UI와 브라우저에 최적화되어 있지,
00:01:16연산 집약적인 워크플로나 컴파일러에는 그다지 최적화되어 있지 않다고요. 이유야 명확합니다. 싱글
00:01:22스레드 방식이라 추상 구문 트리(AST)나 타입 검사를 처리할 때 단일 코어 접근 방식으로는
00:01:27확장성에 한계가 있기 때문이죠. 기술적으로 워커(Worker)에 작업을 분산할 수도 있지만
00:01:32데이터의 직렬화/직렬화 해제가 필요해 속도가 느려지고 메모리 부담이 커집니다. 게다가
00:01:38이 모든 것을 관리하는 복잡성도 다뤄야 하죠. 그래서 목적에 딱 들어맞는
00:01:43언어인 Go를 선택해 획기적인 성능 향상을 이뤄냈습니다. Go는 컴파일 언어라
00:01:48해석 단계를 거치지 않고 CPU에서 컴파일된 코드를 직접 실행하며,
00:01:54공유 메모리 기반으로 여러 실행 스레드를 동시에 손쉽게 돌릴 수 있는 훌륭한 동시성 모델을 갖추고 있습니다.
00:02:00덕분에 단 하나의 코어가 아닌 컴퓨터의 모든 코어를 활용할 수 있게 되었죠.
00:02:06속도 향상의 원인은 대략 반반입니다. 절반은 네이티브 코드로 작동하는 데서 올리고,
00:02:12나머지는 공유 메모리 동시성에서 옵니다. Go는 이 작업에 있어 최적의 언어입니다.
00:02:17단순히 Go가 더 빠른 것을 넘어, 문제 해결에 투입할 자원 자체가 늘어난 셈이죠. 결과가
00:02:23이를 증명해 줍니다. 수치를 보면 130만 줄의 VS Code 코드는 구형 컴파일러에서 125.7초가 걸렸지만
00:02:3210.6초 만에 끝나 11.9배 향상되었고, BlueSky 프로젝트는 24.3초에서 2.8초로 8.7배 향상되었습니다.
00:02:42Playwright는 12.8초에서 1.5초로 줄어 8.7배 빨라졌죠. 재미있게도 Better Stack 구독에는
00:02:49단 1초밖에 안 걸립니다. 앞으로 격차는 더 벌어질 것입니다. 단일 코어 속도는
00:02:54예전만큼 빨라지지 않지만, 코어 수는 늘어나고 있으니까요. 예로 제가 사용하는 M3 Max에는
00:03:0014개나 되는 코어가 있습니다. 대학 시절 쿼드코어 Intel i7으로
00:03:06괴물 같은 조립 PC를 맞췄던 기억이 나네요. 기존 JavaScript 컴파일러는 그 코어 중 딱 하나만 썼지만,
00:03:11Go를 이용하면 모든 코어의 잠재력을 이끌어냅니다. 코어가 많을수록
00:03:17더 뛰어난 성능을 얻게 되죠. 이 기기에서 대형 프로젝트를 버전 6으로 컴파일하면 45초가
00:03:24걸리는 데 반해, 버전 7에서는 3초대까지 단축할 수 있습니다.
00:03:29컴파일 과정에는 여러 단계가 있고 타입 검사는 그중 하나일 뿐입니다. Go는
00:03:344개의 타입 체커를 띄워 각각 코드베이스의 4분의 1씩 검사하도록 만듭니다. 하지만
00:03:39속도를 더 끌어올릴 수 있죠. 컴파일 시 체커 옵션을 12로 설정하면 더욱 빠른 성능을 얻을 수 있습니다.
00:03:45TypeScript 7과 6의 차이를 보기 위해 내 기기에 VS Code 저장소를 받았습니다.
00:03:51기본적으로 제 기기의 `tsc`는 이제 TypeScript 7을 가리킵니다. 진단 명령을
00:03:57실행해 보면 5.4초가 걸렸고, 대부분의 시간은 타입 검사(Check time)에
00:04:02소요되었습니다. (4.7초) 이것 역시 더 단축할 수 있습니다.
00:04:08`--checkers 12` 플래그를 더해주면 전체 시간이 5.4초에서 3.5초로 줄어듭니다.
00:04:15이 과정에서 검사 시간이 깎여나간 거죠. 4.7초였던 검사 시간이 2.9초까지 떨어졌습니다. 이제 동일한
00:04:20명령을 실행하되 이번에는 TypeScript 6을 써보겠습니다. 시간이 좀
00:04:23걸릴 테니 빠르게 넘어가죠. 잠시 기다린 결과, TypeScript 6은
00:04:28모든 코어를 다 활용해 3.5초 만에 끝낸 버전 7에 비해 45.3초나 걸렸습니다.
00:04:36내 M3 Max 칩 기준 무려 15배나 향상된 셈입니다. 3.5초라는 수치는
00:04:43여기서 나온 것이죠. 물론 이렇게 하면 다른 프로세스의 자원을 훔쳐 오겠지만,
00:04:47아무것도 안 하고 있다면 시스템 자원을 100% 활용하는 편이 낫습니다. 이제 새 컴파일러의 실제 코드를
00:04:52살펴보며 Go가 어떻게 이런 성능을 냈는지 알아보죠. 여기 파일 내의 모든 선언을 수집하고
00:04:57어느 스코프에 속하는지 파악하는 `bindSourceFiles` 함수가 있습니다.
00:05:03수천 개에 달할 수도 있는 파일을 다룰 때, 각 파일을 순회하면서 바인딩 작업을 큐에 넣고
00:05:09모두 완료되기를 기다립니다. 가장 놀라운 점은 여러 코어로 작업이 어떻게
00:05:14분산될지 신경 쓸 필요가 없다는 것입니다. Go의 런타임이 알아서 처리해 주죠. 스레드를 생성하거나
00:05:20코어 간의 복잡한 통신을 관리할 필요 없이, 단지 할 일을 전달하기만 하면 알아서 처리 방식을 찾아냅니다.
00:05:26JavaScript에서도 거의 똑같은 코드를 작성할 수 있지만, CPU 바운드 작업에서는 무의미합니다.
00:05:32Promise가 병렬 처리되는 것처럼 착각하게 만들어도 여전히 단일 스레드에서 순차 실행될 뿐입니다.
00:05:38워커(Worker)를 쓰는 대안도 있지만 객체를 직접 공유할 수 없고 SharedArrayBuffer를 통한 바이트 단위 공유만 가능합니다.
00:05:43따라서 파싱된 구문 트리를 워커로 전달하려면 전체를 직렬화해서 복사한 다음
00:05:48반대편에서 다시 재구성해야 합니다. 대용량 파일에서는 그 비용이 본 작업보다 클 수 있습니다.
00:05:53기본적으로 이러한 점들 때문에 Go가 CPU 바운드 작업에 구조적으로 훨씬 우수합니다.
00:05:58모든 동시성을 대신 처리해 주는 런타임이 있고, 공유 메모리가 있어 객체를
00:06:03복사할 필요 없이 곧바로 전달할 수 있죠. 컴파일 시간 외에 체감되는
00:06:07가장 큰 부분은 언어 서버(LSP)의 속도일 것입니다. 대규모 TypeScript 코드베이스에서 작업해 본 사람이라면
00:06:13타입 검사가 끝날 때까지 기다리는 고통을 다 알죠. Intel Mac을 쓸 때는 그 고통이 뼈에 사무쳤습니다. 몇 년 전
00:06:20프로젝트를 진행할 때 저장소를 열면 빨간 물결선이 나타나기까지
00:06:24최대 2분까지 멍하니 기다려야 했습니다. 코드를 조금 수정할 때마다
00:06:29엄청나게 둔해졌죠. 개발자 경험은 최악이었고, 누구도 그 코드베이스를 건드리고 싶지 않아 했습니다.
00:06:34반면 새 언어 서버를 사용하면 IDE에서 즉각적인 피드백을 받게 됩니다.
00:06:40파일을 열어 수정하면 밀리초 단위 만에 곧바로 에러 표시를 확인할 수 있죠. 설령
00:06:46엄청나게 거대한 코드베이스에서 작업하더라도 말이죠. 성능 외에도 새 언어 서버는 더욱 안정적입니다.
00:06:51타입 검사가 멈춰 버려서 IDE를 재시작해야 했던 일이 대폭 줄어들었습니다. TypeScript 7은
00:06:57언어 서버 명령 실패율을 80% 이상 낮췄고, 서버 크래시는 60% 이상 줄였습니다.
00:07:04벽에 노트북을 던지는 일이 줄었으니 환경 보호에도 꽤 이로울 겁니다.
00:07:08MS가 지구 환경까지 생각할 줄은 몰랐네요. 이번 업데이트는 완전 재작성이 아닌
00:07:13'이식'이라는 점도 짚고 넘어갈 만합니다. TypeScript 팀은 새 컴파일러가 기존 버전과
00:07:19완벽히 호환되도록 세심히 공을 들였습니다. 속도를 제외하면 차이점조차 느끼지 못할 겁니다.
00:07:24하지만 본인 프로젝트에서 바로 TypeScript 7을 돌려볼 수 있어도, 자주 쓰는
00:07:29패키지들의 호환 업데이트를 기다려야 할 수 있습니다. 프로그래밍 방식 API가 아직 제외된 상태라,
00:07:35해당 API에 의존하는 typescript-eslint, ts-jest, ts-node 같은
00:07:42패키지들은 7.1 버전이 나올 때까지 다소 지연될 것입니다. 현재 정식 버전 TypeScript 7을 받으실 수 있지만,
00:07:47VS Code용 TypeScript 7 확장 프로그램은 직접 설치하셔야 합니다. 기본 패키지도 추후
00:07:53업데이트되겠지만, 지금은 마켓플레이스에서 'TypeScript 7' 확장을 설치하기만 하면
00:07:58모든 것이 정상적으로 작동합니다. TypeScript 7의 상세 기능들을 확인하고 싶다면
00:08:03해당 내용을 정리해둔 관련 영상 링크를 확인해 보세요. 이번 분석 영상이 마음에 드셨다면
00:08:08Better Stack을 구독해 주세요. 유용한 정보가 되었길 바라며, 이제
00:08:12TypeScript 7이 가져다줄 압도적인 개발 속도를 직접 경험해 보세요. 저도 아주 즐겁게
00:08:16사용하게 될 것 같네요. 시청해 주셔서 감사드리며, 다음 영상에서 다시 찾아뵙겠습니다.