WE ARE TYPED!

타입은 언제나 옳다.

무스마는 Node 프로젝트에서 TypeScript를 적극적으로 사용하고 있습니다.

그것이 모두가 편하고 안전한 길이라고 믿습니다.

바쁘신 분들을 위해 결론부터

그냥 JavaScript를 쓰더라도 일단 TypeScript 프로젝트로 세팅을 해놓으십시오.
그리고 하던대로 계속 하십시오. 만약 결심이 선다면 TypeScript를 시작하십시오!

따라하시면 됩니다.

# 프로젝트 디렉터리로 이동해서
$ cd [프로젝트 경로]

# npm이든 yarn이든 사용해서 devDependencies로 패키지 설치
$ npm install typescrpt --save-dev
$ yarn add typescript --dev

# npm이든 yarn이든 사용해서 TypeScript 프로젝트로 초기화합니다.
$ npx tsc --init
$ yarn run tsc --init

# tsconfig.json 파일이 생깁니다. (끝)
$ cat tsconfig.json

그리고 계속 JavaScript로 개발하셔도 됩니다. 기존 개발 프로세스에 전혀 영향을 주지 않습니다.

다만 언제든지 TypeScript를 사용할 수 있도록 준비만 했습니다.

본격적으로 TypeScript를 사용할 결심이 섰다면 계속해서 아래 내용을 읽어주세요.

왜 TypeScript인가?

Type의 중요성을 아시는 분이라면 공감하실테지만,
Type 시스템 자체에 대해서 의문이 든다면 다음 섹션 ‘왜 Type인가?‘를 읽어보십시오.

TypeScript는 JavaScript에 Type 표기를 할 수 있도록(type annotation) 한 JavaScript의 superset입니다.

이미 React 프로젝트에서 prop-typesflow를 써보신 분들도 있을 겁니다.

prop-types는 React Component에서만 사용하기 때문에 사용 범위가 매우 제한적입니다.

flow처럼 linter 수준의 타입 체커로는 아무래도 TypeScript와 같이 언어 수준으로 갖춘 타입 시스템을 따라오기 힘듭니다.

이미 TypeScript는 사실상 표준이라고 봐도 될 것 같습니다.

제대로 관리되고 있는 자바스크립트 패키지 중에서는, TypeScript에서 사용할 수 있는 Type Definition File(*.d.ts)을 제공하든지, 아예 전체 프로젝트가 타입스크립트로 재작성되고 있습니다.

요즘에 특히 오픈소스 소프트웨어 분야에서 활약하는 Microsoft에서 지원한다는 것도 든든하고 매력적입니다.

왜 Type인가?

Java, C# 같은 언어는 컴파일 타임에 타입이 결정되는 정적 타입 언어(static typed language)입니다.

반면에 JavaScript, Python, Ruby 같은 언어는 실행 중에 비로소 타입을 알 수 있는 동적 타입 언어(dynamic typed language)라고 합니다.

비슷한 말로 Typed-Language와 Untyped-Language로 나누기도 합니다. 이 분류는 (언어에 타입이 없다는 것이 아니라) 소스 코드에 타입을 명시하느냐 하지 않느냐로 구분하는 것입니다.

그런데 중요한 것은 Type이 없는 언어는 없다는 것입니다.

단지 소스 코드 자체에 타입에 대한 정보가 같이 있든지, 아니면 여러분의 머리 속에 있든지의 차이입니다.

  Typed Untyped
타입 정보의 위치 소스 코드 소스 코드를 읽는 여러분의
대뇌 피질 뉴런 어딘가(…)
컴파일러 타입 추론 기능 O
덕분에 코드 양도 줄어듦
X
컴파일러 타입 검증 기능 O
타입이 잘못되면 빌드 자체가 안 됨
X
실행하다가 붕괴
IDE 자동 완성 기능 O
object tree를 타고 nested, nested 쭉쭉 내려가도 뭐가 있는지 다 뜸
X
문맥상 제한적인 추론
IDE 참조 탐색 기능 O (deterministic)
어디에 사용되었는지 100% 추적
X
그냥 뇌가 열일해서 문자열 검색으로 찾아
IDE 리팩터링 기능 O X
만들 땐 쉬워도 고칠 땐 아니란다
코드 양 다소 많음
타입 추론과 syntactic sugar가 들어가면 개선 Java가 문제다
다소 적음
그리고 나중에 고통 받음

반론: 우리는 Untyped 언어로도 잘 해왔다?

여러분은 지금 소스 코드를 보고 머리속에 타입이 그려질 테지만, 처음 보는 사람은 단번에 이해하기 어렵습니다.
그리고 여러분이 나중에 다시 보더라도 어렵습니다.

한동안 JavaScript 프로젝트를 개발하고 또 유지보수를 했습니다.

JavaScript의 유연함과 간결함이 개발 초기에는 매력적이라도 나중에 갈수록 유지보수하기가 정말 힘들었습니다.

어느 언어에나 장단점이 있듯이 개발 속도와 유지보수성에서 trade-off가 존재하기 마련입니다.

물론 JavaScript, Python, Ruby 같은 언어로도 대형 프로젝트를 개발하고 유지보수하시는 분들도 있습니다.

저는 그렇게 생각합니다. 어떤 부분을 기술에 의존할수록 사람이 하던 능력이 쇠퇴할 수 있습니다.

예를 들면 옛날에는 가족이나 친구들의 전화번호 정도는 외우고 다녔습니다.

그런데 휴대전화가 등장하고 주소록 기능을 탑재하면서, 전화번호를 일일이 기억하고 다니는 사람은 요즘 드뭅니다.

심지어는 가족의 전화번호를 모르는 사람도 있습니다.

제가 Java나 Scala(typed 언어의 챔피언)를 주로 하다보니 정적 타입이 없으면 머리가 어수선하고 불안해지는 이유가 바로 그런 것 같습니다.

나는 이제 틀렸어… (머리 속 타입 추론 기능 disabled)

하지만 요즘 굳이 주소록 기능을 배제하고 전화번호 암기를 고집하는 사람도 없습니다.

그리고 기술적으로 달라진 요즘 세상에서는, 주소록을 단순히 전화번호 저장하는 용도로 사용하지 않습니다.

주소록 기능 없이는 당장 카카오톡 같은 것도 못 쓰죠.

마찬가지로 정적 타입 시스템도 컴파일러만 쓰는 게 아닙니다.

IntelliJ나 VSCode 같은 도구도 정적 타입 시스템과 연동하면 효율이 극대화됩니다.

JavaScript 프로젝트를 TypeScript 프로젝트로 바꾸면서 숨겨진 오류도 많이 잡아냈습니다.

저는 요즘 세상에 TypeScript의 존재를 매우 다행스럽게 생각합니다.

흐릿한 기록이 또렷한 기억보다 낫다

그러나 사실상 개발자의 기억은 흐릿할 수 있어도, 소스 코드가 흐릿할 일은 절대 없다.

적어도 프로그래밍에서는 기록된 소스 코드에 비해 기억은 늘 형편없다는 것을 인정해야 합니다.

타입 정보를 소스 코드에 담는 대신 여러분의 뛰어난 두뇌(?)를 이용해서 머리 속에서 타입 정보를 재구성한다면,

여러분이 치매에 걸릴 확률을 감소시켜줄 것입니다.(…)

그러나

타입 정보를 소스 코드에 담으면 여러 사람이 행복합니다.

  • 소스 코드에 타입 정보가 있으므로, 여러분은 소스 코드를 그대로 인지하면 됩니다.
    (품질 구린 두뇌 내장형 타입 추론을 안 해도 됩니다.)
  • 컴파일러도 소스 코드에 담긴 타입 정보를 이용할 수 있습니다.
    (유용한 warning과 error를 발생시켜 엉터리 프로그램이 멀쩡히 빌드되어 배포될 가능성을 낮춰줍니다.)
  • IDE는 소스 코드로부터 각종 메타 정보를 추출하여 개발 편의성을 제공할 것입니다.
    (탐색, 참조, 자동 완성, 리팩터링 등)
  • 새로 들어온 여러분의 동료가 소스 코드를 내려받아 들여다보고 도대체 이게 무슨 타입인지 머리를 뜯고 고민하지 않아도 됩니다.

여러분의 두뇌로 타입 추론을 하지 말고, 여러분보다 똑똑한 컴파일러가 판단하도록 합시다.

여러분의 손발을 수고롭게 하지말고, 여러분보다 똑똑한 IDE가 대신 하도록 합시다.

결론: TypeScript를 씁시다.

모두가 행복해지는 길

# 프로젝트 디렉터리로 이동해서
$ cd [프로젝트 경로]

# npm이든 yarn이든 사용해서 devDependencies로 패키지 설치
$ npm install typescrpt --save-dev
$ yarn add typescript --dev

# npm이든 yarn이든 사용해서 TypeScript 프로젝트로 초기화합니다.
$ npx tsc --init
$ yarn run tsc --init

# tsconfig.json 파일이 생깁니다. (끝)
$ cat tsconfig.json

감사합니다.


References