안녕하세요. IT 엘도라도 에 오신 것을 환영합니다.
글을 쓰는 것은 귀찮지만 다시 찾아보는 것은 더 귀찮습니다.
완전한 나만의 것으로 만들기 위해 지식을 차곡차곡 저장해 보아요.   포스팅 둘러보기 ▼

타입스크립트 (TypeScript)

[TypeScript] Triple-Slash Directives (/// <reference . . . />)

피그브라더 2020. 12. 30. 13:40
 

Documentation - Triple-Slash Directives

How to use triple slash directives in TypeScript

www.typescriptlang.org

 

Triple-Slash 디렉티브는 하나의 XML 태그를 포함하는 한 줄 짜리 주석이다. 디렉티브란 JavaScript 코드로 컴파일이 되진 않지만 컴파일러에게 컴파일에 도움이 될 만한 어떠한 정보를 알리는 부분을 의미한다. Triple-Slash 디렉티브는 참조해야 할 선언 파일의 경로를 컴파일러에게 알려주는 역할을 수행하며, 앞서 말했듯 별도의 JavaScript 코드로는 컴파일 되지 않는다. 컴파일 후에는 단순한 주석의 형태로 남게 된다.

단, 이는 파일의 맨 위에 있을 때만 유효하다. 즉, 주석이나 또 다른 Triple-Slash 디렉티브가 아니고서는 이것보다 먼저 등장하면 안 된다. 만약 그렇다면 이는 단순한 한 줄 짜리 주석으로 취급되며, 어떠한 특별한 의미도 지니지 않게 된다.

 

1. /// <reference path=". . ." />

/// <reference path=". . ." /> 디렉티브는 파일들 사이에서 의존성을 선언하는 역할을 수행하며, 가장 많이 사용되는 형태의 Triple-Slash 디렉티브이다.

 

Triple-Slash 디렉티브는 컴파일 과정에서 특정 파일들이 컴파일 목록에 포함되도록 한다. 또한 이 디렉티브는 --out 혹은 --outFile 플래그를 사용할 때 출력 파일들을 원하는 순서로 정렬하기 위한 방법으로도 사용된다. 참조되는 파일들은 전처리(Preprocessing) 과정에 통과하고 나면 입력 순서대로 출력 파일 위치에 생성이 되기 때문이다.

 

👉 Preprocessing input files

컴파일러는 모든 Triple-Slash 디렉티브들을 해석하기 위해 입력 파일들에 대해 전처리 작업을 가장 먼저 수행한다. 그 과정에서 참조되는 파일들이 컴파일 목록에 포함이 된다.

해당 과정은 루트 파일들에서부터 시작한다. 루트 파일은 커맨드 라인에서 입력으로 전달된 파일, 혹은 tsconfig.json 파일에서 files 프로퍼티로 지정된 파일을 의미한다. 이러한 루트 파일들은 지정된 순서대로 전처리가 진행된다. 어떤 하나의 파일을 컴파일 목록에 포함하기에 앞서, 그 파일에 존재하는 모든 Triple-Slash 디렉티브들을 전처리 하고 그 타겟 파일들을 컴파일 목록에 포함한다. Triple Slash 디렉티브들은 깊이 우선 방식, 즉 파일에서 발견되는 순서대로 해석이 진행된다.

/// <reference path=". . ." /> 디렉티브는 이를 포함하고 있는 파일의 경로를 기준으로 상대적으로 해석된다. 여기에는 가리키는 파일의 확장자까지 정확히 작성해줘야 한다.

 

👉 Errors

존재하지 않는 파일을 참조하는 것은 에러를 발생시킨다. 또한 자기 자신을 가리키는 Triple Slash 디렉티브를 작성하는 것도 에러를 발생시킨다.

 

👉 Using --noResolve

만약 --noResolve 플래그를 지정한다면 Triple Slash 디렉티브들은 완전히 무시된다. 즉, 이들은 새로운 파일들을 컴파일 목록에 포함시키지 않으며, 출력 파일들의 순서에도 전혀 영향을 미치지 않게 된다. 이 플래그를 지정하면 커맨드 라인에 전달된 입력 파일 말고는 컴파일 목록에 포함되지 않는데, 컴파일 목록에 포함되지 않을 파일을 가리키는 Triple Slash 디렉티브는 아무 의미 없기 때문이다.

 

2. /// <reference types=". . ." />

의존성을 선언하는 역할의 /// <reference path=". . ." /> 디렉티브와 유사하게, /// <reference types=". . ." /> 디렉티브는 특정 패키지에 대한 의존성을 선언하는 역할을 수행한다.

 

이러한 패키지 이름의 해석 과정은 비-상대적 import의 모듈 해석 과정과 상당히 유사하다. 즉, /// <reference types=". . ." /> 디렉티브들은 특정 패키지에 대한 import에 견주어 볼 수 있다.

 

예를 들어, 어떤 한 선언 파일 안에 /// <reference types="node" />를 작성한다면 이는 해당 선언 파일이 @types/node/index.d.ts 파일에 선언된 타입 정보를 사용한다는 것을 의미하며, 따라서 이 경우 해당 패키지는 해당 선언 파일과 함께 컴파일 목록에 포함이 되어야 한다. (물론 전역으로 타입 정보가 선언되어 있는 파일일 때만 유효하다. 그렇지 않으면 어차피 import를 통해서만 사용할 수 있기 때문이다. 이와 관련해서는 @types/react/index.d.ts@types/react/global.d.ts를 참고하자.)

 

👉 선언 파일 참조 과정 → 비-상대적 import의 모듈 해석 과정과 유사

EX) /root/src/moduleA.ts 파일에 작성된 /// <reference types="moduleB" /> 코드

 

1. [typeRoots 프로퍼티에 지정된 경로]/moduleB/package.json (types 프로퍼티 참조)
2. [typeRoots 프로퍼티에 지정된 경로]/moduleB/index.d.ts
3. /root/src/node_modules/moduleB.d.ts
4. /root/src/node_modules/moduleB/package.json (types 프로퍼티 참조)
5. /root/src/node_modules/moduleB/index.d.ts
6. /root/src/node_modules/@types/moduleB.d.ts
7. /root/src/node_modules/@types/moduleB/package.json (types 프로퍼티 참조)
8. /root/src/node_modules/@types/moduleB/index.d.ts
9. /root/node_modules/moduleB.d.ts
10. /root/node_modules/moduleB/package.json (types 프로퍼티 참조)
11. /root/node_modules/moduleB/index.d.ts
12. /root/node_modules/@types/moduleB.d.ts
13. /root/node_modules/@types/moduleB/package.json (types 프로퍼티 참조)
14. /root/node_modules/@types/moduleB/index.d.ts
15. /node_modules/moduleB.d.ts
16. /node_modules/moduleB/package.json (types 프로퍼티 참조)
17. /node_modules/moduleB/index.d.ts
18. /node_modules/@types/moduleB.d.ts
19. /node_modules/@types/moduleB/package.json (types 프로퍼티 참조)
20. /node_modules/@types/moduleB/index.d.ts

 

👉 참고 (보충 학습 필요)

  • 이 디렉티브는 .d.ts 파일을 직접 작성할 때 사용하면 좋다.
  • 컴파일 과정에서 생성되는 선언 파일들의 경우, 컴파일러가 자동으로 /// <reference types=". . ." />를 포함시켜준다. 생성된 선언 파일에 /// <reference types=". . ." />이 포함되었다는 것은 해당 파일이 해당 패키지의 선언 파일을 사용한다는 것과 동일한 의미이다.