Post

모듈 내보내기 오류

부트캠프 마지막 팀프로젝트를 진행하며 api는 snake_case로, 코드는 camelCase로 작성하기로 규칙을 정했습니다. 코드를 작성할 때 매번 camelCase로 변환해줘야하는 것이 불편하다는 생각이 들었고, 그래서 camelCase로 변경해주는 라이브러리 camelcase-keys를 사용하고자 했습니다.

패키지를 설치하고, 코드를 작성하기 위해 공식 문서에 나와있는대로 import 를 사용하여 해당 모듈을 불러왔는데, 다음과 같은 오류가 발생하였습니다.

1
2
3
4
5
6
7
8
9
10
11
12
const camelcase_keys_1 = __importDefault(require("camelcase-keys"));
^
Error [ERR_REQUIRE_ESM]: require() of ES Module /Users/hyemin/Desktop/hyemin/myMoney/backend/node_modules/camelcase-keys/index.js from /Users/hyemin/Desktop/hyemin/myMoney/backend/build/middlewares/convertToCamelCase.js not supported.
Instead change the require of index.js in /Users/hyemin/Desktop/hyemin/myMoney/backend/build/middlewares/convertToCamelCase.js to a dynamic import() which is available in all CommonJS modules.
at Object.<anonymous> (/Users/hyemin/Desktop/hyemin/myMoney/backend/build/middlewares/convertToCamelCase.js:7:42)
at Object.<anonymous> (/Users/hyemin/Desktop/hyemin/myMoney/backend/build/app.js:14:30)
at Object.<anonymous> (/Users/hyemin/Desktop/hyemin/myMoney/backend/build/index.js:3:15) {
code: 'ERR_REQUIRE_ESM'
}

Node.js v18.18.2
[nodemon] app crashed - waiting for file changes before starting...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import { NextFunction, Response } from "express";
import camelcaseKeys from "camelcase-keys";

import { CustomRequest } from "./authentication";

export const convertToCamelCase = (
  req: CustomRequest,
  res: Response,
  next: NextFunction
) => {
  // req.body에 있는 snake_case 키들을 camelCase로 변환
  if (req.body) {
    req.body = camelcaseKeys(req.body, { deep: true });
  }
  next();
};

Node.js에서 CommonJS와 ES Module 간의 호환성 문제로 발생한 오류이다.

문제 상황

  • Node.js 프로젝트에서 타입스크립트 파일을 자바스크립트로 컴파일할 때 CommonJS 모듈 방식으로 컴파일함
  • 그런데 최신 버전의 camelcase-keys 모듈은 ES Module 형식으로 작성되어 있음
  • CommonJS 방식으로 ES Module 형식의 camelcase-keys 모듈을 require()하려고 하니 호환성 문제가 발생

처음에는 이러한 문제를 파악하지 못하고, 구글링을 해보았을 때 동적으로 모듈을 가져오면 된다고 하여 동적으로 모듈을 가져오는 시도도 해보았다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import { NextFunction, Response } from "express";

import { CustomRequest } from "./authentication";

export const convertToCamelCase = async (
  req: CustomRequest,
  res: Response,
  next: NextFunction
) => {
  // camelcase-keys 모듈을 동적으로 가져옴
  const camelcaseKeys = (await import("camelcase-keys")).default;

  if (req.body) {
    req.body = camelcaseKeys(req.body, { deep: true });
  }
  console.log(req.body);
  next();
};

역시나 근본적인 문제가 해결되지 않아, 오류가 발생하였다.

1
2
3
4
5
6
7
8
9
10
11
12
const camelcase_keys_1 = __importDefault(require("camelcase-keys"));
^

Error [ERR_REQUIRE_ESM]: require() of ES Module /Users/hyemin/Desktop/hyemin/myMoney/backend/node_modules/camelcase-keys/index.js from /Users/hyemin/Desktop/hyemin/myMoney/backend/build/middlewares/convertToCamelCase.js not supported.
Instead change the require of index.js in /Users/hyemin/Desktop/hyemin/myMoney/backend/build/middlewares/convertToCamelCase.js to a dynamic import() which is available in all CommonJS modules.
at Object.<anonymous> (/Users/hyemin/Desktop/hyemin/myMoney/backend/build/middlewares/convertToCamelCase.js:7:42)
at Object.<anonymous> (/Users/hyemin/Desktop/hyemin/myMoney/backend/build/app.js:14:30)
at Object.<anonymous> (/Users/hyemin/Desktop/hyemin/myMoney/backend/build/index.js:3:15) {
code: 'ERR_REQUIRE_ESM'
}

Node.js v18.18.2

근본적인 문제인 ES module로 작성된 모듈을 commonJS로 컴파일할 때 발생하는 호환성 오류를 해결하기 위해 번들러를 사용하여 모듈을 commonjs방식으로 변환하는 방법, 다운그레이드 하기 등 여러 방법들이 있다. 프로젝트 마감시간이 촉박하여 camelcase-keys 모듈을 CommonJS 방식으로 작성된 이전 버전으로 다운그레이드하여 사용하기로 결정했다. 실행 결과, 잘 작동하는 것을 확인할 수 있었다.

하지만 이 방법은 새로운 기능이나 보안 패치같은 기능들을 지원받을 수 없기 때문에, 프로젝트가 완료 후에 리팩토링을 통해 개선할 예정이다.

1
"camelcase-keys": "^5.2.0",
This post is licensed under CC BY 4.0 by the author.