개요
Nest.js에서 외부 라이브러리를 이용하고자 할때 NPM과 같은 패키지 매니저를 이용해서 외부 라이브러리을 관리한다.
외부 라이브러리의 버전에 따라서, 지원하는 표준에 따라서 여러 오류를 맞이하게 된다.
TypeScript까지 잘 지원하는 라이브러리가 많아지길 기원하며, 이 포스트를 작성해본다.
배경지식
ECMAScript
JavaScript의 기반이 되는 표준이다. 즉, JavaScript는 ECMAScript의 사양을 준수하는 범용 스크립팅용 언어인 것이다.
CommonJS & ESM
CommonJS
JavaScript의 역사는 정적인 HTML을 동적으로 표현하기 위해서 만들어졌다. 그러다보니 웹 브라우저에 탑재되었고, HTML 문서상에서 작성을 하다 보니, 모듈이라는 개념이 없었다. 그러나 라이언달에 의해서 Node.js가 만들어지면서, 모듈을 사용하기 위한 CommonJS가 생겼다. 즉, CommonJS는 Node.js용 JavaScript를 패키징 하는 전통적인 방식이다. 동기식으로 동작하는 CommonJS는 가져오기와 내보내기가 가능해졌고, 이를 통해 NodeJS의 생태계가 발전해왔다.
ESM(ECMAScript Module)
이름에서 보이듯, ECMAScript 표준에서 ESM이라는 표준 모듈 시스템을 만들었고, Node.js 12 부터 ECMAScript Modules를 지원하고 있다. 즉, 모듈 재사용을 목적으로 JavaScript 코드를 패키징하는 공식 표준 형식이다.
"Node.js에는 CommonJS, ESM 2개의 모듈 시스템이 존재한다"
문제점
CommonJS | ESM | |
동작 | 동기적 | 비동기적 |
사용법 | require / module.exports | import / export |
loader | CommonJS module loader | ESM module loader |
위의 차이점을 보면 서로 호환되기 어렵다는 문제점이 보인다. 실제로 ESM에서는 CommonJS를 import 할 수 있지만, CommonJS에서 ESM을 require 할 수는 없다. 바로 이 문제가 "require() of ES Module" 오류를 의미 하는 것이다.
본문
NPM에서 패키지를 확인해보면, 특정 패키지에서 더 이상 CommonJS를 지원하지 않는 다는 본문 내용이나, ESM 형식을 따르지 않는 패키지들이 많이 존재한다.
Nest.js에서 ESM 사용하기
got 13.0.0을 기준으로 패키지가 ESM만 지원하게 되었다. 따라서 CommonJS 패키지에서 import 하면 다음과 같은 오류가 발생한다.
Type Error가 발생하는 이유는 CommonJS는 FileSystem을 기반으로 Type Definition을 탐색하지만, ESM은 exports field의 값을 읽어 Type Definition을 탐색하기 때문이다. 즉, got 패키지의 type을 읽지 못한다.
어찌저찌 해결 하면 다음과 같은 오류가 발생할 것이다.
ESM Error가 발생했다. 현재 패키지가 CommonJS이므로 TypeScript가 JS로 컴파일 하면서, require()를 사용한다. 당연한 이유지만, 위에서 말했듯이 CommonJS 패키지에서는 ESM 패키지를 사용할 수 없다. 따라서 require()를 통해서 로드 할 수 없음을 알려준다.
위 문제를 해결 하려면, 현재 작업중인 CommonJS 패키지를 ESM 패키지로 변경한다.
Node.js 설정(package.json)
{
...
"type": "module",
"exports": "./index.js",
"engines": {
"node": ">=16"
},
...
}
TypeScript 설정(tsconfig.json)
{
"compilerOptions": {
"module": "node16",
"moduleResolution": "node16",
...
}
...
}
위 와 같이 설정하면 작업 중인 패키지가 ESM으로 변경된다. 따라서 ESM 외부 패키지를 이용하더라도 Type Definition 오류가 발생하지 않는다.
컴파일 결과도 ESM 문법으로 바뀐 것을 알 수 있다.
References
https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c