문제 상황
Node.js 스크립트를 실행했는데 다음과 같은 오류가 날 수 있습니다.

Error: Cannot find module 'package-name'
또는 아래처럼 local file path가 표시될 수 있습니다.
Error: Cannot find module './utils/file'
이 오류는 Node가 require() 또는 import에 전달된 값을 실제 package, file, export path로 찾지 못했다는 뜻입니다.
가장 중요한 단서는 따옴표 안에 있는 module 이름입니다.
이 값이 package 설치 문제인지, local file path 문제인지, module 형식 문제인지 판단해야 합니다.
원인
Cannot find module은 보통 다음 원인 중 하나로 발생합니다.
- 현재 프로젝트에 package가 설치되어 있지 않습니다.
node_modules가 삭제되었거나 다른 폴더에 설치되어 있습니다.- 명령을 잘못된 working directory에서 실행했습니다.
- local import path에
./,../, 정확한 file name이 빠졌습니다. - CommonJS와 ESM 문법을 잘못 섞었습니다.
- package의
package.json에서exports필드로 deep import를 막고 있습니다. - Windows에서는 통과한 대소문자 차이가 Linux 또는 CI에서 실패합니다.
Node는 package name과 file path를 다르게 해석합니다. 먼저 import 대상이 package인지 local file인지 분류해야 합니다.
빠른 해결
빠진 값이 express, react, lodash 같은 package name이라면 프로젝트에 설치합니다.
npm install package-name
npm ls package-name
빠진 값이 ./, ../, /로 시작한다면 file path입니다.
이 경우 package를 설치하지 말고 실제 파일 이름과 상대 위치를 확인합니다.
Node가 어느 위치에서 실행 중인지 확인합니다.
node -p "process.cwd()"
현재 위치가 project root가 아니라면 package.json이 있는 폴더로 이동한 뒤 다시 실행합니다.
단계별 해결 방법
1. Package인지 File인지 먼저 구분하기
아래는 package import입니다.
const express = require("express");
아래는 local file import입니다.
const helper = require("./utils/helper.js");
Package import라면 Node는 현재 module 주변의 node_modules부터 parent directory 방향으로 package를 찾습니다.
Local file import라면 import하는 파일을 기준으로 상대 경로를 따라갑니다.
npm install utils/helper 같은 명령을 실행하지 마세요.
경로가 local file이라면 설치가 아니라 path 수정이 필요합니다.
2. 빠진 Package 다시 설치하기
Package import라면 다음을 실행합니다.
npm install package-name
npm ls package-name
npm ls가 (empty) 또는 오류를 보여주면 이 프로젝트에 해당 package가 설치되지 않은 것입니다.
Lockfile이 있는 프로젝트라면 repo에서 이미 쓰는 package manager를 따르는 것이 좋습니다.
npm install
Yarn 또는 pnpm 프로젝트라면 lockfile을 섞지 말고 해당 명령을 사용합니다.
yarn install
pnpm install
3. Working Directory 확인하기
많은 Cannot find module 오류는 명령을 잘못된 폴더에서 실행해서 발생합니다.
macOS와 Linux:
pwd
node -p "process.cwd()"
ls package.json
Windows PowerShell:
Get-Location
node -p "process.cwd()"
Get-ChildItem package.json
현재 폴더에 package.json이 없다면 project root로 이동합니다.
cd path/to/project
npm install
node app.js
4. Relative Path 수정하기
Local file에서 가장 흔한 실수는 ./를 빠뜨리는 것입니다.
잘못된 예:
const helper = require("utils/helper");
올바른 예:
const helper = require("./utils/helper.js");
utils/helper는 package name처럼 해석됩니다.
./utils/helper.js는 현재 module 기준의 local file을 읽으라는 뜻입니다.
파일 이름의 대소문자도 확인해야 합니다.
require("./UserService.js");
실제 파일 이름이 userService.js라면 Windows에서는 동작할 수 있지만 Linux CI나 production server에서는 실패할 수 있습니다.
5. CommonJS와 ESM 규칙 확인하기
CommonJS는 require()를 사용합니다.
const helper = require("./helper.js");
ESM은 import를 사용합니다.
import helper from "./helper.js";
package.json에 "type": "module"이 있으면 .js 파일은 기본적으로 ESM으로 처리됩니다.
ESM에서 local import를 할 때는 file extension을 포함하는 편이 안전합니다.
import { formatName } from "./format-name.js";
ESM 프로젝트에서 CommonJS 파일이 필요하면 .cjs를 사용합니다.
const config = require("./config.cjs");
CommonJS 프로젝트에서 ESM 파일이 필요하면 .mjs를 사용하거나 프로젝트 전체 전환을 의도적으로 진행합니다.
오류 하나를 없애기 위해 "type": "module"만 바꾸면 다른 import가 연쇄적으로 깨질 수 있습니다.
6. Package Export Path 확인하기
어떤 package는 아래 import만 허용할 수 있습니다.
import thing from "some-package";
하지만 아래 deep import는 막을 수 있습니다.
import thing from "some-package/internal/file";
최근 package들은 exports 필드로 외부에서 접근 가능한 public path를 제한할 수 있습니다.
Deep import가 실패한다면 package 문서를 확인하고 지원되는 public path로 import해야 합니다.
Package를 업그레이드한 뒤 예전 internal path가 사라져 이 오류가 나는 경우도 많습니다.
7. require.resolve로 진단하기
CommonJS 환경에서는 Node가 package를 어디서 읽는지 직접 확인할 수 있습니다.
node -p "require.resolve('package-name')"
Node가 찾지 못하면 이 명령도 MODULE_NOT_FOUND 오류를 냅니다.
이 경우 application logic 문제가 아니라 module resolution 문제라는 점을 확인할 수 있습니다.
Local path도 같은 방식으로 테스트할 수 있습니다.
node -p "require.resolve('./utils/helper.js')"
처음 오류가 난 명령과 같은 폴더, 같은 실행 방식에서 테스트해야 합니다.
해결 확인 방법
수정 후 처음 실패했던 명령을 그대로 다시 실행합니다.
node app.js
프로젝트에 script가 있다면 함께 확인합니다.
npm test
npm run build
npm start
같은 import에 대해 더 이상 Cannot find module이 발생하지 않으면 해결된 것입니다.
다른 오류가 난다면 이제 module resolution 다음 단계의 문제를 별도로 보면 됩니다.
흔한 실수
- 실제로는 relative path 문제인데 package를 설치합니다.
- project root가 아닌 parent folder에서
node app.js를 실행합니다. - 한 repo에서
npm install,yarn install,pnpm install을 섞어 사용합니다. - local file import에
./를 빠뜨립니다. - ESM local import에서
.js확장자를 생략합니다. - 문서화된 public export가 아닌 package 내부 경로를 import합니다.
- Linux에서만 실패하는 파일 이름 대소문자 차이를 놓칩니다.
공식 문서
관련 글
- JavaScript 오류 ‘Uncaught ReferenceError: is not defined’ 해결 방법
- JavaScript TypeError: ‘…’ is not a function 해결 방법
- JavaScript jQuery is not defined 오류 해결 방법
자주 묻는 질문
이 글은 언제 먼저 적용하면 좋나요?
오류 메시지, 실행한 명령, 사용 중인 OS와 버전을 먼저 기록한 뒤 이 글의 원인별 순서대로 확인하는 것이 좋습니다.
초보자가 가장 먼저 확인할 부분은 무엇인가요?
처음에는 환경 변수, 설치 경로, 권한, 캐시처럼 재현 가능성이 높은 항목부터 확인하세요. 그다음 로그와 설정 파일을 비교하면 원인을 좁히기 쉽습니다.
더 찾아볼 때 어떤 키워드를 쓰면 좋나요?
추가 검색할 때는 “Node.js Cannot find module 오류 해결 방법” 같은 핵심 문구와 error message, version, Windows, GitHub Pages, Jekyll 같은 실제 환경 키워드를 붙이면 더 정확한 결과를 얻기 쉽습니다.
Leave a comment