2015-06-26

타입스크립트의 단점

 지난번 글에서 너무 타입스크립트를 사용하면서 얻게 되는 장점만 말한 것 같아서 이번 글에서는 타입스크립트를 사용하면서 맞게 되는 단점들을 말해보도록 하겠다.

 타입스크립트의 단점은 명확하다. 타입스크립트와 자바스크립트를 섞어서 쓸 수 있다는 점이다.

 타입스크립트로 컴파일한 코드는 자바스크립트가 되기 때문에 타입스크립트로 작성한 모듈을 자바스크립트에서 불러올 수 있다.
 하지만 이렇게 사용한다면, 지난번 글에서 말한 타입스크립트를 사용하는 장점 중 하나인 타입 체크를 위한 verbose 한 코드를 작성하지 않아도 되는 장점이 사라진다. 자바스크립트에서 사용될 것을 가정하고 코드를 작성할 경우는 여전히 verbose 한 타입 체크 코드를 작성해야 한다. 이것은 내가 자바스크립트 코드를 타입스크립트를 포팅하면서 딱히 좋은 점을 느끼지 못했던 이유이기도 하다.
 하지만 이는 자바스크립트를 사용했다면 언제나 발생했을 문제가 타입스크립트를 사용할 때 다시 발생하는 것뿐이다. 자바스크립트를 사용해야 하는 환경에서 타입스크립트를 사용하지 않을 이유는 되지 않는다.

 이번에는 반대로 타입스크립트를 사용하면서 자바스크립트로 작성된 모듈을 불러오는 경우를 보자. 타입스크립트에서는 자바스크립트의 모듈을 그대로 가져다 쓸 수 있다. 덕분에 타입스크립트 생태계는 크게 노력하지 않고 자바스크립트의 생태계를 흡수할 수 있었다. 하지만 이것은 동시에 단점이 되기도 한다. 자바스크립트로 작성된 모듈은 타입 추론을 할 수 없어서 모든 API가 any 타입이 되고, 결국 이 부분이 unsafe 한 부분이 되기 때문이다.

 이런 문제를 해결할 수 있도록 타입스크립트는 모듈의 타입만 분리해서 선언하는 선언 파일을 사용할 수 있게 해놓았다. 선언 파일과 함께 사용하면 자바스크립트로 작성된 모듈을 사용할 때도 잘못된 타입을 사용하면 타입 에러를 내준다.
 물론 선언 파일을 만드는 것도 비용이다. 하지만 이는 큰 문제가 되지 않는다. 유명한 라이브러리에 대해서는 이미 DefinitelyTyped에 많은 선언 파일이 만들어져 있다. DefinitelyTyped에 만들어지지 않은 라이브러리도 있고, 버전이 맞지 않는 경우도 있다. 이에 대해서는 직접 만들거나 수정해서 사용해야 한다. 하지만 이는 큰 문제가 되지 않는다. 어차피 외부 모듈을 사용하려면 어떤 함수가 어떤 인자를 통해서 실행되고 어떤 값을 리턴하는지 파악을 해야 한다. 그렇지 않으면 (특히 자바스크립트같이 동적 타입의 언어들에서는) 무언가 문제가 발생하기 십상이다. 따라서 그저 파악한 API의 시그니쳐를 코드로 옮겨 적으면 된다.


 다시 한 번 강조하지만, 타입스크립트의 단점은 다른 정적 타입 언어들보다 불안한 부분들일 뿐이다. 자바스크립트보다 못하는 점은 없다. 타입어노테이션이나 선언 파일이라는 약간의 비용을 들여서 타입 세이프한 코드를 만든다는 큰 이득이 있어서, 자바스크립트를 사용해야만 하는 환경에서 타입스크립트를 사용하지 않을 이유는 전혀 없다.
 그래서 나는 앞으로도 자바스크립트를 사용할 것이다. 아니 타입스크립트 대신 Google의 AtScript나 Facebook의 flow를 사용할 수는 있겠지만, 정적인 타입 분석이 붙지 않은 상태의 자바스크립트를 이용해 코딩할 생각은 없다.

2015-06-22

TypeScript와 함께 한 4개월

 내가 타입스크립트를 처음 쓰게 된 것은 올해 3월이었다. 당시에 알바를 하고 있던 회사에서 작성하던 서버 사이드 자바스크립트 코드의 안정성을 향상하기 위해 타입스크립트로 포팅하는 일을 시작하였고, 당시 그 팀의 구성원은 전원 너무 바빴기 때문에 다른 일을 하던 내가 불려가서 포팅하게 되었다.

 사실 처음에 포팅을 하기로 했을 때는 흥미로운 일이라고 생각하지만, 딱히 의미 있는 일이라고는 생각하지 않았었다. 당시 코드는 이미 뼈대에 해당하는 부분이 대부분 완성되어 있었고, 그 대부분은 이미 타입의 개념이 없이 짜인 코드였었다. 그래서 단순히 타입스크립트로 옮겨도 별 이득이 없을 것이고, 완벽하게 포팅하는데 들어가는 노력에 대비해서 안정성을 확보할 수 있을지에 대해 확신이 없어서였다.

 그래도 돈을 받고 하기로 한 일이었으므로 작업은 시작하였다. 우선 이미 구현되어있는 코드가 너무 많았기 때문에 초반에는 손에 닿는 파일부터 타입스크립트로 변환하며 작업을 하였다. 그 뒤로 한 3개월은 코드를 바꾸는 일만 했다.

 하지만 이때까지는 타입스크립트의 장점을 딱히 느낄 수 없었다. 변환하는 과정에서 몇몇 버그를 잡았지만, 이미 타입이 중요한 부분은 underscore.js를 이용해서 타입체크를 하고 있었기에 타입스크립트가 추가로 해주는 일이 거의 없었다. 변환하는 과정에서 몇몇 버그를 발견하기는 했지만, 충분한 유닛 테스트로 잡을 수 있는 버그들이었기에 딱히 타입스크립트를 사용해야 한다고 느끼지 못했다. 오히려 리팩토링에 너무 많은 시간이 들었기 때문에 비용 대비 효용이라는 측면에서 비효율적이라고 느꼈다. 그러다가 타입스크립트에 대한 인식이 바뀌게 된 것은 다음 프로젝트를 시작하면서부터였다.

 다음 프로젝트를 시작하게 된 것은 지난 5월 말이었으니 거의 한 달 정도 전이다. 하게 된 일은 기존의 스칼라로 작성되었던 beyond 프레임워크node.js에서 돌도록 포팅한 beyond.ts를 만드는 것이었는데, 이번 프로젝트는 처음부터 타입스크립트를 이용해서 작성하였다.

 타입스크립트를 제대로 이용하면서 느껴진 타입스크립트의 장점은 크게 4가지이다.

 우선 자바스크립트를 이용할 때 귀찮은 부분인 타입 체크하는 코드나 테스트를 작성하지 않아도 된다는 것이다. 자바스크립트뿐 아니라 파이썬이나 루비 같은 동적 타입 언어들도 가지는 문제인데 자바스크립트는 타입점검을 하거나 타입을 테스트하기 위해 코드가 verbose 해지기 쉬운데, 타입스크립트를 사용하면 이럴 이유가 전혀 없다.

 두 번째로 안심하고 코딩할 수 있다. 기존에 자바스크립트를 사용할 때는 장황한 테스트를 작성하여 높은 커버리지를 유지하여야 했다. 그렇지 않으면 사소한 실수건 의도적인 수정이었건 간에 코드를 잘못 변경하여 문제가 생기는 경우가 가끔 발생하는데, 타입스크립트는 이런 문제들을 컴파일 타임에 점검해주기 때문에 사전에 막을 수 있었다.

 세 번째로 ES6의 기능들을 사용할 수 있었다. 사실 이건 타입스크립트의 장점이라고 하기는 뭐하지만, 타입스크립트는 대부분의 ES6를 ES5나 ES3로 변환시켜준다. 덕분에 fat arrow, class, const와 let, 다양한 parameter 등 많은 기능을 사용할 수 있다.

 마지막으로 내가 사용하는 라이브러리를 더 쉽게 파악할 수 있다. TypeScript에서는 기존의 JavaScript로 작성된 npm 라이브러리를 그대로 사용할 수 있다. 대신에 타입 추론을 해주기 위해서 선언 파일이 있어야 한다. 하지만 사용하는 모든 모듈에 대해서 선언 파일을 직접 만들 필요는 없고, DefinitelyTyped를 통해서 다른 사람들이 이미 구현해둔 파일을 받을 수 있다. 이것은 사용할 API를 이해하는 데 꽤 많은 도움을 준다.

 물론 타입스크립트에 단점이 없는 것은 아니다. 하지만 타입스크립트를 사용하여 얻을 수 있는 장점이 더 크다고 생각된다. 정확히는 타입스크립트를 사용함으로 인해 들어가는 비용에 비해 타입스크립트를 통해 얻을 수 있는 이득이 훨씬 크다고 생각한다.
 그래서 다음에도 자바스크립트를 사용할 일이 생긴다면, 타입스크립트를 사용할 것이다. 아니 타입스크립트가 아닌 Google의 AtScript나 Facebook의 flow를 사용하게 될 수는 있지만, 최소한 자바스크립트를 동적 타입 언어인 그대로 사용하지는 않을 것이다.

2015-06-21

변하지 않아도 되는 코드는 죽은 코드 뿐이다.

 내가 병특을 시작했던 회사에서 있었던 일이다.

 그 회사는 그냥 흔한 SI 회사였는데 덕분에 코드 퀄리티는 크게 보장할 수 없었다. 정말이지 많은 것이 나를 괴롭혔지만, 그중에서 나를 가장 괴롭혔던 건 옛날에 작성되어 관리 안 되는 코드들이었다. 그 회사는 SI 회사답게 유지보수라는 명목으로 몇 년 전에 팔았던 프로젝트의 유지보수라는 이름으로 고정 수익을 벌고 있었는데, 그중에서 가장 심한 건 10년 전에 작성되었던 프로젝트도 있었다.

 그 날도 여전히 그 코드에 괴롭힘당하고 있었다. 내가 괴로워하고 있으니 당시 내 사수였던 개발자 J가 와서 한마디 해줬었다.

너무 그러지 마. 이거 그래도 네 학교 선배 K가 병특할때 짰던 코드야. 조금씩 변경된 부분이 있지만 대부분 네 선배가 짠 거야.
 위로의 말이었는지, 괴로워하는 거 티 내지 말라는 의미였는지 나는 모른다. 내가 아는 것은 그저 이게 내가 퇴사를 결심하게 된 계기가 되었다는 것이다. 어째서 저 말이 그렇게 내 마음을 흔드는 말이 되었을까?

 당시에 K가 퇴사한 건 거의 10년 가까이 된 일이었다. 즉, 저 코드는 작성된 지 거의 10년이 된 코드라는 것이다. 거기에 유지 보수하면서 추가된 기능 외에 큰 틀은 전혀 건드리지 않았었다는 것이다. 뭐 J는 10년이 지날 만큼 안정적으로 작성된 코드라고 말하고 싶었을지도 모르겠다. 하지만 10년을 변하지 않은 코드가 좋은 코드일 리가 없다.

 지난 10년간 프로그래밍 도구는 많은 발전이 있었다. 단적으로 생각해봐서 2003년에 visual studio 6.0으로 코드를 작성하는 것과 2013년에 visual studio 2013으로 코드를 작성하는 것을 생각해보자. 아무도 2013 대신 6.0을 선택할 사람은 없을 것이다. 10년이라는 시간은 이 정도의 발전을 가지고 왔다. 도구뿐이 아니다. 개발 방법론, 설계법, 분석법 모든 측면에서 지난 10년간 많은 발전이 있었다. 즉, 10년 전에 좋은 코드였다고 하더라도 지금 기준에서 좋은 코드라는 보장은 할 수 없다.

 당시 그 회사는 코드의 이력관리를 전혀 안 했기 때문에1) 당시 K가 작성한 코드가 어떤 코드였는지 알 수 없었다. 하지만 내가 보고 있던 코드는 10년 전 기준으로도 좋은 코드였을 거라고 말할 수 없는 그런 코드였다. 개발에서 가장 중시하는 abstraction이나 flexibility를 전혀 고려하지 않고 전역변수들로 가득 차 있던 그런 코드를 아직 수정하지 않고 있던 회사를 도저히 믿을 수 없었다.

 심지어 그 당시 코드는 10년간 전혀 변경이 없던 코드도 아니었다. 앞에서도 말했듯이 당시에 유지 보수라는 명목으로 계약하고 꾸준히 이것저것 기능들을 추가했었다. 글 불구하고 코드스멜들을 전혀 제거하지 않았다는 것은 더더욱 그 회사를 믿지 못하는 계기가 되었다.


1) 난 21세기에 이메일로 패치도 아닌 코드 전체를 주고받으며 작업하게 될 거라고는 상상도 못 했다.