2012년에 마이크로소프트가 TypeScript를 발표했을 때, 반응은 시큰둥했다. 또 마이크로소프트가 뭔가 만들었네. JavaScript로 충분한데 왜? 그로부터 10년이 지난 지금, TypeScript는 프론트엔드의 사실상 표준이 됐다.

JavaScript는 10일 만에 만들어진 언어다. 작은 스크립트를 작성할 때는 유연함이 편리했다. 하지만 수만 줄의 코드를 여러 명이 함께 작성하면 이야기가 달라진다. 함수가 어떤 타입을 받는지 모른다. 객체에 어떤 속성이 있는지 모른다. 리팩토링하면 어디가 깨지는지 모른다. 런타임에 터져야 알 수 있다.

JavaScript의 한계를 느낀 사람들이 대안을 만들기 시작했다. CoffeeScript는 문법을 예쁘게 바꿨지만 타입 문제는 해결하지 못했다. Dart는 구글이 JavaScript를 대체하려고 만들었지만 브라우저가 지원하지 않아서 실패했다. Flow는 페이스북이 만든 타입 체커로 TypeScript와 비슷한 시기에 나왔다.

TypeScript가 이들을 제치고 승리한 이유가 있다. 첫째, JavaScript의 상위 집합이다. 기존 JavaScript 코드를 그대로 쓸 수 있다. 파일 확장자만 ts로 바꾸면 일단 동작한다. 점진적으로 타입을 추가하면 된다. 둘째, 타입이 선택적이다. 급할 때는 any로 넘어가고 나중에 고치면 된다. 셋째, 마이크로소프트의 지원이다. VS Code가 터졌다. 그리고 VS Code는 TypeScript로 만들어졌고, TypeScript 지원이 압도적으로 좋았다. 넷째, 생태계가 따라왔다. DefinitelyTyped 프로젝트가 수천 개의 라이브러리에 타입 정의를 추가했다.

결국 TypeScript가 제공하는 건 실행 전에 오류를 잡는 것이다. 런타임에 터지면 사용자가 고통받는다. 컴파일 타임에 터지면 개발자만 고생한다. 프로젝트가 커질수록 이 차이는 극명해진다.

물론 TypeScript가 완벽한 건 아니다. 복잡한 타입을 작성하다 보면 타입 시스템과 싸우느라 정작 로직은 안 짠다. 빌드 단계가 추가된다. 타입은 컴파일 후에 사라져서 런타임 검증이 필요하면 별도로 해야 한다.

TypeScript가 표준이 된 건 프론트엔드 프로젝트의 규모가 커졌기 때문이다. 예전에는 jQuery로 DOM 몇 개 조작하면 끝이었다. 지금은 SPA가 수십만 줄의 코드를 가진다. 이 규모에서 타입 없이 개발하면 머릿속으로 모든 걸 기억해야 한다. 사람의 기억력에는 한계가 있다. 타입 시스템이 대신 기억해준다.