NestJS에서 작업 중 간단한 스크립트를 작성할 일이 있어 ts파일로 작성했다.
스크립트 실행은 npm script를 통해서 아래와 같이 작성하였고, 실행을 시키니 Cannot find module... 에러가 났다.
"script:start": "ts-node main.ts"
스크립트 파일에서 프로젝트 내에 있는 모듈을 가져오는 부분이 있었다.
근데 다른 모듈의 경로를 상대경로가 아닌, 비 상대 경로로 가져오고 있었고, 이는 tsconfig.json 파일에서 path
옵션을 통해 alias로 지정해놓은 상태였다.
단순하게 예를 들어보자.
프로젝트가 아래와 같이 되어있다고 가정해보자.
packages/user/src
├── config
│ ├── app-config.schema.ts
│ ├── app-config.value.ts
│ └── index.ts
├── email
│ ├── email.constant.ts
│ └── index.ts
├── main-app.controller.ts
├── main-app.module.ts
├── main-app.service.ts
├── main.ts
├── phone
│ └── phone.service.ts
└── validation-array.dto.ts
tsconfig.json
"module": "commonjs",
"paths": {
"@packages/user": [
"packages/user/src"
],
"@packages/user/*": [
"packages/user/src/*"
],
}
packages/user/email/email.constant.ts에 값을 하나 입력해둔다.
packages/user/email/email.constant.ts
export const EMAIL = 'MODULE FOUND!!!';
이제 프로젝트 루트 위치(packages 폴더 위치)에 EMAIL 값을 출력하는 스크립트 하나를 작성해보자.
main.ts
import { EMAIL } from "@packages/user/email";
function main() {
console.log(EMAIL);
}
main();
그리고 실행시켜보면
에러가 나버린다.
왜일까?
Typescript에서 모듈을 해석할 때의 전략은 Classic
과 Node
2가지가 있다.
tsconfig.json에 작성된 compilerOptions 옵션 중 module의 값이 AMD | System | ES2015인 경우 Classic
, 나머지는 모두 Node
로 된다.
나의 경우 commonjs로 설정했기 때문에 Node
전략으로 해석되는데,
Node
전략에서의 비 상대적 경로를 해석하는 방법은 루트까지 올라가면서 node_modules 안에서 파일을 첫 번째로, 폴더를 다음으로 찾는다고 한다.
자세한 과정은 이곳에서 확인하실 수 있습니다.
위에서 내가 작성한 기준으로 살펴보면
main.ts에서 @packages/user/email를 import 하고 있으므로
node_modules/packages/user/email.ts
.
.
.
node_modules/packages/user/email/index.ts
만약 스크립트 파일을 packages/main.ts에서 작성했다고 한다면
packages/node_modules/packages/user/email.ts
.
.
packages/node_modules/packages/user/email/index.ts
.
.
node_modules/packages/user/email.ts
.
.
node_modules/packages/user/email/index.ts
이런식으로 찾아 나갈거다.
결국 찾지 못하게 되므로 node_modules 폴더가 아닌 tsconfig.json의 path 경로를 읽어 불러올 수 있도록 tsconfig-paths/register 모듈을 사용하여 해결해보자.
package.json
"script:start": "ts-node -r tsconfig-paths/register main.ts"
정상적으로 동작하는 것을 확인할 수 있다.