티스토리 뷰
[Typescript] tsconfig.json의 lib
1. lib 옵션의 사용
타입스크립트가 빌드 될 때 참조하는 tsconfig.json
의 컴파일 옵션중에 lib
이라는 항목이 있습니다. 이 항목의 의미를 알아봅시다.
// tsconfig.json
{
"CompilerOptions": {
"target": "es5",
"module": "commonjs",
"lib": [
"dom",
"es5",
"es2015.promise"
]
}
}
이 tsconfig.json
에 등장하는 중간에 lib
의 내용을 보면 배열형태로 사용할 라이브러리들을 정의하고 있습니다. 만약 lib
항목을 정의하지 않았다면 target
항목에서 지정한 ECMAScript의 버전에 따라 기본값이 정의됩니다.
- ES5의 기본 값:
dom
,es5
,scripthost
- ES6의 기본 값:
dom
,dom.iterable
,es6
,scripthost
위의 기본 값 대신에 커스텀하게 라이브러리를 쓰려고 할 때, lib
을 정의하여 사용합니다.
사용 예를 하나 들겠습니다. 위 예제처럼 빌드 될 target
은 es5
로 정의되어 있습니다. 그런데 작성한 코드나, 코드에서 참조하는 모듈들(node_modules
)에서 ES6에서 등장한 Promise
를 사용하려면 es2015.promise
라는 라이브러리를 위처럼 정의하여 라이브러리 인젝션을 해줘야 합니다.
2. lib 옵션에 사용할 수 있는 값들
lib에는 사용할 수 있는 문자열은 아래와 같습니다.
- ES5
- ES6
- ES2015
- ES7
- ES2016
- ES2017
- ESNext
- DOM
- DOM.Iterable
- WebWorker
- ScriptHost
- ES2015.Core
- ES2015.Collection
- ES2015.Generator
- ES2015.Iterable
- ES2015.Promise
- ES2015.Proxy
- ES2015.Reflect
- ES2015.Symbol
- ES2015.Symbol.WellKnown
- ES2016.Array.Include
- ES2017.object
- ES2017.SharedMemory
- ES2017.TypedArrays
- esnext.asynciterable
- esnext.array
- esnext.promise
아시겠지만, ES6
는 ES2015
와 동일하고 ES7
는 ES2016
와 동일합니다. 따라서 ES6
를 사용하게 되면, ES2015
와 동일하며, ES2015.*
즉, ES2015의 모든 항목들을 전부 로딩합니다.
3. 실제로 참조하는 lib은 무엇일까?
코드를 분석하며 좀 더 딥하게 다이브(Deep Dive) 해봅시다.
3.1. lib 파일들은 어디에 있을까요?
보통 설치한 타입스크립트 모듈에 존재합니다. 예를 들어, npm install -g typescript
와 같이 글로벌 영역에 타입스크립트를 설치 했다면, Linux/macOS 에서는 /usr/local/lib/node_modules/typescript
에 설치가 됩니다. 죄송하지만 Windows에서는 잘 모르겠습니다. ^_^;
$ ls -l /usr/local/lib/node_modules/typescript/lib
... (중략)
lib.d.ts
lib.dom.d.ts
...
lib.es2015.d.ts
lib.es2015.promise.d.ts
...
위 처럼 아까 보셨던 문자열과 거의 동일한 이름으로 lib
파일이 정의되어 있습니다. 파일들을 열어보면 ECMAScript 규격에 정의된 자바스크립트 객체들에 대한 인터페이스들이 정의되어 있는 것을 보실 수 있습니다.
// lib.es5.d.ts
... (중략)
interface Function {
apply(this: Function, thisArgs: any, argArray?: any): any;
call(this: Function, thisArgs: any, ...argArray: any[]): any;
...
}
interface Number {
toString(radix?: number): string;
...
valueOf(): number;
}
...
위 처럼 원시 타입(Primitive Type)의 인터페이스들도 정의되어 있구요. Math
같은 자바스크립트 내장 객체들의 인터페이스도 정의되어 있습니다.
3.2. 라이브러리 로딩 과정
이제 tsc.js
의 코드를 보며 실제 컴파일 과정에서 라이브러리를 읽는 과정을 잠깐 보겠습니다.
//tsc.js
{
name: "target",
shortName: "t",
type: ts.createMapFromTemplate({
"es3": 0,
"es5": 1,
"es6": 2,
"es2015": 2,
"es2016": 3,
"es2017": 4,
"esnext": 5
}),
...(후략)
},
{
name: "lib",
type: "list",
element: {
name: "lib",
type: ts.createMapFromTemplate({
"es5": "lib.es5.d.ts",
"es6": "lib.es2015.d.ts",
"es2015": "lib.es2015.d.ts",
"es7": "lib.es2016.d.ts",
...
"es2015.core": "lib.es2015.core.d.ts",
"es2015.generator": "lib.es2015.generator.d.ts",
...(후략)
}),
}
...(후략)
}
위 코드는 tsc.js
컴파일러가 옵션을 파싱하는 부분입니다. target
옵션과 lib
옵션에 대해 위처럼 매핑되어있습니다. lib.es2015.d.ts
파일을 잠깐 열어보면요.
// lib.es2015.d.ts
/// <reference no-default-lib="true" />
/// <reference path="lib.es2015.core.d.ts" />
/// <reference path="lib.es2015.collection.d.ts" />
/// <reference path="lib.es2015.generator.d.ts" />
/// <reference path="lib.es2015.promise.d.ts" />
/// <reference path="lib.es2015.iterable.d.ts" />
/// <reference path="lib.es2015.proxy.d.ts" />
/// <reference path="lib.es2015.reflect.d.ts" />
/// <reference path="lib.es2015.symbol.d.ts" />
/// <reference path="lib.es2015.symbol.wellknown.d.ts" />
/// <reference path="lib.es5.d.ts" />
보시다시피 XML형식으로 다른 ts
파일들을 참조하도록 되어있습니다. 실제 구현부는 lib.es2015.core.d.ts
같은 파일들에 있습니다.
// tsc.js
function getDefaultLibFileName(options) {
switch (options.target) {
case 5: return "lib.esnext.full.d.ts";
case 4: return "lib.es2017.full.d.ts";
case 3: return "lib.es2016.full.d.ts";
case 2: return "lib.es6.d.ts";
default: return "lib.d.ts";
}
}
이 함수는 서두에 말씀 드렸던 lib
을 정의하지 않았을 때, target
에 대한 기본 라이브러리를 읽어오는 부분입니다. lib.es2015.d.ts
파일이 XML 의 참조 형식을 빌렸기 때문에, 실제 구현부의 집합인 lib.es6.d.ts
라는 파일을 추가 정의하여 사용하는것 같습니다. lib.es6.d.ts
파일은 lib.es2015.*.d.ts
의 모든 내용을 합친것과 같습니다. 파일이름에 full
이 붙은 esnext
, es2017
, es2016
역시 같은 맥락입니다.
4. 결론
타입스크립트를 빌드하며 lib
이 도대체 뭘까 궁금했습니다. 그러다가 rxjs를 공부하는 와중에 target: "es5"
로 컴파일러 옵션을 주고 빌드를 하면 다음과 같은 에러가 발생하는 문제때문에 딥하게 공부해보기 시작했습니다.
node_modules/@reactivex/rxjs/dist/package/Observable.d.ts(58,60): error TS2693: 'Promise' only refers to a type, but is being used as a value here.
node_modules/@reactivex/rxjs/dist/package/Observable.d.ts(73,59): error TS2693: 'Promise' only refers to a type, but is being used as a value here.
일단은 lib: ["es5", "dom", "es2015.promise"]
혹은 lib: ["es6", "dom"]
으로 해결이 되는 문제였습니다. 어떻게 lib
을 사용하는것이 효과적인지, 두 방법간에 어떤 차이가 있는지 궁금해서 시작하게 된 공부였습니다.
제 생각은 성능상에는 큰 상관 없을 것 같습니다. ^^ es2015.promise
처럼 라이브러리를 인젝션하면 모듈화를 할때 조금 더 효율적이긴 할 것 같지만 성능상에 큰 문제를 발생시킬것 같지는 않습니다. 아무래도 공부가 더 필요한 모양입니다.
문의사항이나 의견이 있으면 언제든 무엇이든 댓글 남겨주세요.
5. 참고
'Javascript&Typescript > Typescript' 카테고리의 다른 글
[번역] Zones(zone.js)를 리버스 엔지니어링해서 찾은 것 (0) | 2018.04.18 |
---|---|
[Typescript] class에서 'this' 를 사용할 때 주의사항 (3) | 2018.04.08 |
- Total
- Today
- Yesterday
- QT
- qemu linux arm
- 리눅스 터미널 색상
- typeScript
- JavaScript
- ansi color
- 안시 컬러
- Angular
- angular2
- ECMA2015
- ZONES
- vim
- 스위프트
- 타입스크립트
- Swift
- C언어
- 안시 색상
- git proxy
- Zone.js
- observable
- zone
- lua table
- NgZone
- 폰트 조정
- Rx.js
- terminal 색
- itoa
- git 설정
- 우분투 16.04
- 챗봇
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |