라벨이 TypeScript인 게시물 표시

[TypeScript] Promise.all에는 인자 개수 제한이 없다

트위터에서 이상한 글을 봤다. TypeScript가 선언한 Promise.alliterable을 받지 않고 인자 개수 제한이 있다는 것이다. 근데 그럴 리가. TypeScript쯤 되는 프로젝트에서 무언가가 스펙과 다른 것으로 보인다면, 코드를 잘못 이해했을 확률이 높다. 코드를 다시 확인해보자.당연히 iterable을 인자로 받는 Promise.all선언도 있다. 다만, 이 선언이 es2015.promise.d.ts가 아닌 es2015.iterable.d.ts에 있을 뿐이다. 타입스크립트 컴파일러 옵션 중 --lib 으로 사용할 라이브러리를 지정할 수 있다. 대부분 es2015, es2018 같은 식으로 버전을 지정하여 포함하는 것이 일반적이라 잘 알려지지 않았지만, es2015.symbol로 Symbol에 대한 선언만 포함하거나, es2015.promise로 Promise에 대한 선언만 포함하는 것이 가능하다. 각 라이브러리는 서로 간에 의존성이 없도록 작성돼 있으며, 특히 iterable에 관련된 선언은 전부 es2015.iterable에서 선언한다. 예를 들어 Map이나 Setes2015.collection에 선언돼 있지만, iterable을 반환하는 entries, values, keys 등의 선언은 전부 es2015.iterable에 선언돼 있다. 마찬가지로 iterable을 인자로 받는 Promise.all 함수도 es2015.iterable에 선언돼있다.iterable을 받는 Promise.all 함수 선언은 es2015.iterable에 선언돼 있는데, es2015.promise에 10개가 더 선언돼있다. 이들은 무엇일까? 사실 이 함수들은 배열을 인자로 받는 함수가 아니라 tuple을 인자로 받는 함수 선언이다. JavaScript에는 임의 개수의 원소를 가지는 배열은 있지만, 고정된 개수의 원소를 가지는 tuple은 없다. 그래서 tuple이 필요할 때 배열을 사용한다. 이를 TypeScript에서는 별도의 타입으로 표시할 수 있도…

2018년 20번째 주

이 포스팅은 그냥 지난 한 주간 읽었던 것들을 정리하는 포스트입니다. 그냥 예전에 봤던 글 중 나중에 필요한데 뭐였는지 기억 안 나는 글들이 있어서 쓰기 시작했습니다.
 보통 하는 일과 관련된 글들이 올라오겠지만 딱히 정해둔 주제는 없고, 그때그때 관심 있었던 것을 읽었기 때문에 지난주에 쓰인 글일 수도 있고 몇 년 전에 쓰인 글일 수도 있습니다.Polkadot: Vision for a Heterogeneous Multi-chain FrameworkCosmos - A Network of Distributed Ledgers블록체인이 쏟아져 나오면서 다른 블록체인과 통신을 어떻게 할 수 없을까에 대해 고민하는 사람들이 나왔다.
예를 들어 지금은 Alice의 비트코인과 Bob의 이더리움을 교환하기 위해서는 양자가 신용하는 Ted가 필요하다. Alice는 비트코인을 Bob은 이더리움을 Ted에게 보내고, 양쪽에게 받은 트랜잭션을 확인한 Ted는 Alice와 Bob에게 이더리움과 비트코인을 보내주는 식이다. 지금은 거래소가 이 역할을 해주고 있다. 하지만 trustless를 가정하고 설계된 블록체인에서 거래소는 가장 약한 고리가 된다. 그래서 이 거래소에 해당하는 역할을 블록체인으로 구성하자는 제안이 나왔고, PolkadotCosmos가 대표적이다.How I targeted the Reddit CEO with Facebook ads to get an interview at Reddit어떤 사람이 공개된 페이스북 프로필을 이용해서 레딧 CEO를 타겟으로 광고를 했다고 한다. 결국, 10$만에 레딧 CEO에게 광고하는 데 성공했다고 한다. 마케터들은 페이스북이 이렇게 유용하다고 생각할 것이다. 근데 사용자 입장에서 반대로 내 신원이 이 정도로 추적된다는 것인데 이런 것을 감수하고 쓸 정도로 페이스북이 매력적인 서비스인지 이해가 안 된다. 사실 사람들이 개인 정보 보호에 그다지 관심 없는 게 아닌가 싶다.To Type or Not to Type:Quantifying D…

Flow vs TypeScript - 왜 나는 아직 타입스크립트를 쓰는가

나는 개인적으로 동적 타입 언어보다 정적 타입 언어를 선호한다. 아니 동적 타입 언어를 싫어한다. 정확히 말하면 동적 타입 언어이기에 생기는 실수에 의한 버그들과 그로 인해 사고에 걸리는 부하를 싫어한다. 그래서 웹 개발을 몇 년을 했지만 여전히 동적 타입 언어인 자바스크립트로 코딩하는 것은 싫어한다. 그 때문에 어지간히 간단한 일이 아니라면, 자바스크립트를 사용할 때 반드시 다른 툴을 붙여 정적분석을 한다.
 자바스크립트의 정적 분석을 위해 사용되는 도구는 크게 2가지로 나뉜다. 마이크로소프트에서 만든 타입스크립트와 페이스북에서 만든 플로우다. 한때는 구글이 타입스크립트를 기반으로 만든 AtScript라는 것도 있었지만, 이는 다시 TypeScript로 합쳐지면서 사라지게 되었다. 타입스크립트와 플로우는 둘 다 자바스크립트를 정적 타입 검사가 가능하도록 만들어주었다. 하지만 접근하는 방향은 완전 다른 방향으로 접근하였다.
 우선 타입스크립트는 2012년에 첫 버전이 나왔다. 타입스크립트의 목표는 자바스크립트로 변환되는 더 쓰기 편하고 안전한 언어를 만드는 것이었다. 어디까지나 자바스크립트로 변환되는 언어를 만드는 것이었기에 문법적 기반을 자바스크립트에 두었다. 다시 말해서 타입스크립트의 문법은 자바스크립트 문법의 슈퍼 셋이다. 자바스크립트의 문법을 기반으로 하여 그 위에 추가적인 기능을 더했다. 추가된 기능에는 class나 enum처럼 사용성을 올리기 위한 기능도 있고, private이나 타입 어노테이션 처럼 안전한 코드를 만들기 위해 추가된 기능도 있다.
 반면에 페이스북의 플로우는 새로운 언어를 정의하지 않는다. 플로우는 ECMAScript 6(a.k.a. ES6)의 타입 검증 도구일 뿐이다. 이미 타입스크립트의 많은 기능이 ES6에 표준으로 들어왔기 때문에 새로운 언어를 만들 필요가 없었다. 플로우는 새로운 언어를 정의하지 않기 때문에 이미 자바스크립트로 작성된 프로그램을 바로 분석할 수 있다. 타입이 모호한 경우에는 어노테이션을 추가하여 타입을 선…

[TypeScript] Type guard - sum type 분리하기

Type guard는 다른 언어에서 보기 힘든 TypeScript만의 독특한 기능으로, 타입 인트로스펙션을 통해 분기한 블록 안에서 해당 변수의 타입을 한정시켜주는 기능을 말한다.

 TypeScript를 사용하다 보면, 하나의 변수가 2개 이상의 타입일 가능성이 있는 경우가 자주 생긴다. TypeScript의 본질이 JavaScript이고 이는 동적 타입 언어이기 때문일 것이다. 이를 위해서 TypeScritp는 any 타입을 이용하거나, 조금 더 안전한 사용을 위해서 유니언 타입을 이용한다. 하지만 유니언 타입의 값은 그 값이 될 수 있는 모든 타입이 공통으로 가지는 함수와 프로퍼티만 이용할 수 있고, 모든 타입이 들어갈 수 있는 함수에만 사용 사용할 수 있다.
 이런 불편함을 없애기 위해서 나온 기능이 type guard이다.

 위의 코드처럼 여러 개의 타입이 될 수 있는 값을 사용하기 전에 인트로스펙션을 이용해서 타입을 확인하고 값을 사용하는 것은 JavaScript에서 볼 수 있는 흔한 패턴이다. 이렇게 타입을 확인하고 나면, 확인한 블록 안에서 그 값은 해당하는 타입이 되는 것이 type guard이다.

 하지만 아직 모든 인트로스펙션에 대해서 type guard가 적용되는 것은 아니다. 현재 type guard가 적용되는 경우는 인트로스펙션이 조건문에 들어가는 if 블록과 그에 따라오는 else 블록뿐이다.
위의 예제처럼 if 블록이 반드시 return 하여 그다음은 else 블록과 다를 바 없는 경우에는 type guard가 적용되지 않는다.

 게다가 모든 인트로스펙션이 가능한 것도 아니고, instanceof를 사용하는 경우와 typeof의 결과가 'number', 'string', 'boolean'이 되는 경우뿐이다. 그래서 underscore 등을 이용해서 타입 체킹을 하는 경우나 인트로스펙션 부분을 함수로 뺀 경우는 type guard가 동작하지 않는다. 이는 TypeScript 1.6에 계획된 …

sfuture - JavaScript에서 concurrent한 프로그램 작성하기

sfuture는 JavaScript에서 사용할 수 있는 컨커런트한 프로그램을 쉽게 작성할 수 있도록 도와주는 라이브러리다. 이름에서 알 수 있듯이, Scala의 Future를 JavaScript로 포팅한 것으로, 내부적으로 ECMA Script 6 promise를 사용하고 있어서, promise가 구현된 환경(node.js 0.12.0 이상, 대부분의 모던 브라우저)에서는 아무런 디펜던시 없이 바로 사용할 수 있다.

 만들게 된 이유는, 전에 rhino engine을 이용해서 Scala로 작성한 beyond라는 게임 서버 엔진이 있었는데, 여러 가지 문제가 있어서 이것을 node.js로 포팅하게 되면서 필요하게 되었다.
 Rhino를 사용할 때는 Java class를 그대로 재사용할 수 있었기에 인터페이스만 수정하는 수준이면 가능했는데, node.js로 포팅해오면서 그럴 수 없게 되었다. 처음에는 Future를 포팅해올지, async등 기존의 라이브러리들을 이용하도록 할지 고민했다.
 하지만 async를 실제로 사용을 해보니, 이것도 결국 콜백 헬을 없앨 수 있는 건 아니고, 오히려 코드가 길어질수록, 가독성만 떨어뜨리는 느낌이라서 결국 새로 구현하였다.

 구현은 타입스크립트로 되어 있지만, publish 전에 컴파일하여 자바스크립트 파일만 배포한다. 원본 소스를 보고 싶으면, 깃헙 리파지토리를 보길 바란다.

타입스크립트의 단점

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

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

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

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

 이런 문제를 해결할 수 있도록 타입스크립트는 모듈의 타입만 분리해서 선언하는 선언 파일을 사용할 수 있게 해놓았다. 선언 파일과 함께 사용하면 자바스크립트로 작성된 모듈을 사용할 때도 잘못된 타입을 사용하면 타입 에러를 내준다.
 물론 선언 파일을 만드는 것도 비용이다. 하지만 이는 큰 문제가 되지 않는다. 유명한 라이브러리에 대해서는 이미 DefinitelyTyped에 많…

TypeScript와 함께 한 4개월

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

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

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

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

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

 …