TechFeedTechFeed
Programming Languages

Cannot find module, 모듈을 찾을 수 없음, node_modules | 지워도 같은 줄이 뜨면 뭐부터 볼까?

Cannot find module은 패키지가 없어서가 아니라 노드가 이름을 찾을 폴더를 지나쳤거나 대소문자가 달라서 난다. node_modules를 지워도 같으면 cwd와 require 이름부터 본다. 크론, 깃허브 액션, 맥과 리눅스 CI, npm ci. 개발자, Node.js, npm, Next.js, 백엔드 기준. 2026년 8월 Node.js·npm 공식 문서.

by

Cannot find module은 패키지가 없어서가 아니라, 노드가 그 이름을 찾을 폴더를 이미 지나쳤거나 파일 이름 대소문자가 달라서 납니다. node_modules만 지워 다시 깔아도 같은 줄이면, 지금 프로세스의 작업 폴더와 require 경로부터 보세요.


로컬 터미널에선 되고 크론이나 깃허브 액션만 모듈을 못 찾는 일, 1인으로 넥스트 사이트를 돌리다 보면 한 번은 만납니다. 제가 쓰는 발행 스크립트도 저장소 밖에서 node를 부르면 바로 이 줄이 납니다.


NODE_PATH를 늘리기 전에 cwd, 패키지 이름, 맥과 리눅스 대소문자부터 맞추면 대부분 끝납니다. 근거는 Node.js 모듈 폴더 탐색에러 코드 문서에 있습니다.


지워도 같은 줄이면 어디를 보나

작업 폴더와 패키지 이름 대소문자부터 맞춥니다. 노드는 현재 디렉터리의 node_modules를 보고, 없으면 한 단계 위 폴더로 올라가며 같은 이름을 찾습니다. 그 사다리를 다 올라갔는데도 없으면 MODULE_NOT_FOUND 또는 Cannot find module을 던집니다.


그래서 rm -rf node_modules && npm ci가 만능이 아닙니다. 설치는 저장소 루트에 됐는데 실행은 홈 폴더나 scripts/ 안에서 하면, 그 cwd 기준으로는 패키지가 안 보입니다. 메시지에 찍힌 경로가 /Users/you/프로젝트인지, 홈인지부터 읽으세요.


패키지 이름 자체도 자주 갈립니다. 저장소에 적힌 이름과 코드의 불러오기 이름이 한 글자라도 다르면 디스크에 파일이 있어도 못 찾습니다. 한국에서 맥으로 짜고 리눅스 통합 환경에서만 깨지는 경우는 거의 대소문자입니다. 혼자 돌리는 새벽 작업도 저장소 밖에서 실행하면 같은 증상이 납니다.


먼저 기억할 것 | 지워 다시 깔기 전에 process.cwd()와 에러에 찍힌 모듈 이름을 나란히 보세요. 설치 위치와 실행 위치가 다르면 같은 줄이 반복됩니다.


노드가 node_modules 폴더를 위로 올라가며 모듈을 찾는 개념 이미지
노드는 현재 폴더의 node_modules부터 루트까지 올라가며 이름을 찾는다

먼저 확인할 세 칸

cwd, 모듈 이름, 대소문자 세 칸이면 원인이 갈립니다. 표로 먼저 나눕니다.


증상먼저 할 일
작업 폴더로컬은 되고 크론·액션만 실패에러 경로와 pwd를 비교, cd 후 실행
패키지 이름방금 넣은 패키지인데 못 찾음package.json dependencies 철자, 스코프 @
대소문자맥은 되고 리눅스 CI만 실패import 경로와 실제 파일명 일치
락파일ci에서만 없음npm ci는 lock 기준, 로컬 npm install과 다름
번들러 alias앱은 되고 노드 스크립트만 실패tsconfig paths는 런타임이 모름

다섯 번째 칸은 별글입니다. @/ 별칭이 넥스트 빌드에선 되고 node scripts/foo.js에선 안 되는 경우는 타입스크립트 경로 설정 문제입니다. 여기서는 순수 노드가 node_modules에서 이름을 못 찾는 줄만 봅니다.


락파일 칸은 피어 의존성 충돌과 자리가 다릅니다. ERESOLVE는 트리를 못 만들고, Cannot find module은 트리는 있는데 실행 순간에 파일을 못 여는 쪽입니다.


cwd와 모듈 이름을 같이 찍기
node -e "console.log('cwd', process.cwd())" ls node_modules/패키지이름 # 에러에 찍힌 이름과 ls 결과가 다르면 철자·대소문자부터

실행 위치를 맞춘 다음 다시 깔기

먼저 저장소 루트에서 실행하고, 그래도 없으면 그때 지워 깔습니다. npm 스크립트는 package.json이 있는 폴더를 cwd로 잡습니다. 셸에서 node scripts/publish.js를 홈에서 치면 cwd가 홈이라 루트의 node_modules를 못 봅니다.


크론·launchd는 특히 그렇습니다. plist나 crontab에 작업 디렉터리를 안 넣으면 홈에서 시작합니다. 절대 경로로 스크립트를 불러도 cwd는 홈입니다. cd /path/to/repo && node scripts/foo.js처럼 디렉터리를 고정하세요.


그다음에야 설치를 다시 합니다. npm ci는 lock이 있어야 하고, lock과 package.json이 어긋나면 설치 자체가 실패합니다. 로컬에서 npm install만 하다가 CI에서 npm ci를 쓰면, 빠진 패키지가 여기 에러로 드러납니다.


루트에서 설치하고 루트에서 실행
cd /path/to/repo pwd npm ci node scripts/foo.js # launchd/cron 예: /bin/bash -lc 'cd /path/to/repo && node scripts/foo.js'
  • [ ] 에러 메시지에 찍힌 모듈 이름을 그대로 복사했다
  • [ ] process.cwd()가 저장소 루트인지 확인했다
  • [ ] ls node_modules/그이름 으로 디스크에 있는지 봤다
  • [ ] 맥/리눅스면 import 경로 대소문자를 파일명과 맞춰 봤다
  • [ ] cwd를 고친 뒤에야 npm ci를 다시 돌렸다

터미널에서 프로젝트 루트로 이동한 뒤 노드 스크립트를 실행하는 장면
크론과 액션은 홈에서 시작할 수 있다. cd 후 실행이 기본이다

맥에선 되고 리눅스만 실패할 때

파일명 대소문자가 import와 다르면 리눅스에서만 납니다. 맥 기본 디스크는 대소문자를 구분하지 않아 Utils.jsutils.js로 불러도 열립니다. 깃허브 액션 우분투는 구분해서 같은 코드가 Cannot find module이 됩니다.


고치는 법은 디스크의 실제 이름에 import를 맞추는 것입니다. 파일을 바꿔 커밋할 때는 깃이 대소문자만 바꾼 변경을 무시할 수 있습니다. git mv로 한 번 다른 이름에 옮겼다가 올바른 이름으로 되돌리면 추적됩니다.


모노레포라면 워크스페이스 패키지 이름과 폴더 이름까지 보세요. packages/App인데 require('app')이면 로컬 링크가 안 붙습니다. 워크스페이스 프로토콜 설정은 패키지 매니저 문서를 따릅니다.


NODE_PATH는 마지막 | 환경변수로 경로를 늘리면 cwd 버그가 숨습니다. 공식 모듈 탐색은 node_modules 사다리가 기본입니다. 경로를 우회하기 전에 실행 위치부터 고치세요.


ENOENT와 같은 줄이 아니다

파일을 못 여는 줄과 모듈을 못 찾는 줄은 원인 칸이 다릅니다. ENOENT는 경로 문자열 자체가 디스크에 없을 때입니다. Cannot find module은 모듈 해석기가 이름을 패키지로 풀어 node_modules 사다리에서 실패한 때입니다.


스크립트 경로 오타, fs.readFile('data.json')의 상대경로, 도커에서 마운트가 빠진 파일은 ENOENT 글에서 다룹니다. 여기서는 require('foo') / import 'foo'가 패키지 폴더를 못 찾는 경우만 봅니다.


포트가 막혀 서버가 안 뜨는 줄은 EADDRINUSE입니다. 모듈 에러와 동시에 보이면, 대개 서버 파일이 의존성을 못 읽어 바인딩 전에 죽은 겁니다. 모듈 줄부터 없애세요.


메시지무엇을 못 찾나다음 글
Cannot find module패키지 이름, node_modules 사다리이 글
ENOENT파일 경로 문자열경로·cwd 글
ERESOLVE설치 트리 피어 충돌npm ERESOLVE 글

맥 개발과 리눅스 CI에서 파일명 대소문자가 갈리는 개념 이미지
맥은 대소문자를 느슨히 보고, 리눅스 CI는 파일명 한 글자까지 맞춘다

참고 자료


내부 연계: npm ERESOLVE 피어 충돌, 포트가 이미 사용 중, 클론 직후 노드 버전, 노드 권한과 크론, 폴더별 환경 변수


인용한 동작은 2026년 8월 공개 문서 기준입니다.


자주 묻는 질문

node_modules를 지워도 같은 줄이 뜹니다. 설치가 잘못된 건가요?

설치보다 실행 위치인 경우가 많습니다. 홈이나 scripts 폴더에서 node를 부르면 루트에 깔린 패키지를 못 봅니다. process.cwd()를 에러 경로와 비교한 뒤에 다시 npm ci를 하세요.


로컬은 되는데 깃허브 액션만 모듈을 못 찾습니다.

대소문자와 npm ci 두 가지를 의심하세요. 맥에서 통과한 import가 우분투에서 실패하고, 로컬 npm install과 CI의 npm ci가 lock을 다르게 읽습니다. working-directory를 저장소 루트로 고정했는지도 보세요.


NODE_PATH를 넣으면 해결되나요?

잠깐 우회는 됩니다. cwd 버그가 숨어서 다음 스크립트에서 같은 사고가 납니다. 공식 탐색은 node_modules 사다리가 기본이니, 실행 위치를 고치는 쪽이 안전합니다.


@로 시작하는 스코프 패키지만 실패합니다.

require('@org/pkg')처럼 슬래시를 포함한 이름 전체를 써야 합니다. @org만 넣거나 대괄호를 빼먹으면 다른 이름을 찾습니다. package.json에 적힌 이름과 한 글자도 같아야 합니다.


넥스트 앱은 되는데 node scripts만 실패합니다.

번들러가 잡아 주는 @/ 별칭은 노드 런타임이 모릅니다. 스크립트는 상대 경로나 패키지 이름으로 바꾸거나, 별칭을 런타임에 연결하는 도구를 따로 써야 합니다. 앱 빌드 성공과 스크립트 성공은 다른 칸입니다.


ERESOLVE와 무엇이 다른가요?

ERESOLVE는 설치 시점에 피어 버전이 어긋나 트리를 못 만드는 줄입니다. Cannot find module은 이미 설치된 이름을 실행 순간에 못 여는 줄입니다. 설치 로그와 런타임 스택을 섞지 마세요.


Cannot find module은 지금 프로세스가 서 있는 폴더에서 그 이름을 못 찾았다는 뜻입니다. cwd를 저장소 루트에 두고, 패키지 이름과 대소문자를 맞춘 다음, 그래도 없으면 npm ci를 하세요. 관련 글: ERESOLVE, 포트 점유, 노드 버전.


Cannot find moduleMODULE_NOT_FOUNDnode_modulesrequirenpm ciNode.jsnpmNext.js대소문자cwd개발자백엔드

함께 보면 좋은 문제 해결

EXPLORE / Programming Languages

이어서 읽어보기

전체 토픽 둘러보기