TypeScript 프로젝트 하다 보면 한 번쯤은 꼭 만나는 에러다.
Cannot find module 'X' or its corresponding type declarations. ts(2307)
빌드도 안 되고, IDE에서도 빨간 줄 잔뜩 그어지면서 당황하게 된다. 이 에러는 발생 원인이 여러 가지라 원인을 제대로 모르면 해결책을 찾아 헤매다 시간만 버린다.
1. 증상
error TS2307: Cannot find module '../utils/logger' or its corresponding type declarations.
error TS2307: Cannot find module '@/components/Button' or its corresponding type declarations.
error TS2307: Cannot find module 'lodash' or its corresponding type declarations.
import 구문에서 빨간 줄이 생기고, tsc 실행 시 컴파일이 실패한다. VSCode 같은 IDE에서도 동일하게 에러가 표시된다.
2. 원인별 분류
크게 4가지 패턴으로 나뉜다.
패턴 1: @types 패키지 누락
서드파티 라이브러리를 설치했지만 TypeScript 타입 정의 패키지를 설치하지 않은 경우다. lodash, express, node 같은 라이브러리는 별도의 @types/xxx 패키지가 필요하다.
# 확인 방법
ls node_modules/@types/
# 해결
npm install --save-dev @types/lodash
npm install --save-dev @types/node
npm install --save-dev @types/express
패턴 2: tsconfig.json 경로 별칭(Path Alias) 미설정
@/, ~/ 같은 경로 별칭을 사용하는데 tsconfig에 paths 설정이 없는 경우다. Vite, Next.js, CRA 등에서 흔하게 발생한다.
// tsconfig.json
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["src/*"],
"~/*": ["src/*"]
}
}
}
tsconfig.json의 paths를 자동으로 인식하지만, Node.js 환경에서 직접 실행할 때는 tsconfig-paths 패키지가 추가로 필요하다.
npm install --save-dev tsconfig-paths
# 실행 시
ts-node -r tsconfig-paths/register src/index.ts
패턴 3: moduleResolution 설정 불일치
Node.js 16+ 혹은 ES Modules를 사용할 때 moduleResolution 설정이 맞지 않는 경우다.
// tsconfig.json
{
"compilerOptions": {
"module": "NodeNext",
"moduleResolution": "NodeNext"
}
}
NodeNext 설정에서는 import 시 파일 확장자를 명시해야 한다.
// ❌ 에러
import { logger } from './utils/logger';
// ✅ 정상
import { logger } from './utils/logger.js';
컴파일된 결과가 .js이기 때문에 소스에서도 .js 확장자를 써야 한다. 처음엔 이상하게 느껴지지만 ESM 스펙이 이렇다.
패턴 4: node_modules 손상 또는 누락
패키지가 설치되어 있는데도 에러가 난다면 node_modules 자체가 손상됐을 가능성이 있다.
# 클린 재설치
rm -rf node_modules package-lock.json
npm install
3. 원인 진단 체크리스트
| 점검 항목 | 확인 방법 | 해결 방법 |
|---|---|---|
| @types 패키지 설치 여부 | ls node_modules/@types/ |
npm i -D @types/xxx |
| tsconfig paths 설정 | tsconfig.json 확인 | baseUrl + paths 추가 |
| moduleResolution 설정 | tsconfig.json 확인 | NodeNext 또는 bundler |
| node_modules 상태 | ls node_modules/[패키지명] |
클린 재설치 |
| 상대 경로 확장자 | import 구문 확인 | .js 확장자 명시 |
4. --traceResolution 으로 정확히 추적하기
어디서 모듈을 찾는지 추적하고 싶다면 이 플래그를 쓴다.
tsc --traceResolution 2>&1 | grep -A 5 "Cannot find module"
TypeScript가 어떤 경로를 탐색했는지 전부 출력해준다. 설정 문제인지, 패키지 문제인지 바로 보인다.
5. 실제 사례 — Next.js에서 @/components 경로 에러
Cannot find module '@/components/Button' or its corresponding type declarations.
Next.js 프로젝트에서 흔히 겪는 케이스다.
// tsconfig.json — 이 설정이 없으면 에러 발생
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["./*"]
}
}
}
Next.js 13+는 프로젝트 생성 시 자동으로 이 설정을 넣어주지만, 수동으로 구성한 프로젝트나 마이그레이션한 경우 누락되기 쉽다.
6. Jest + TypeScript 환경
Jestl��서도 같은 에러가 발생할 수 있다. Jest는 tsconfig의 paths를 직접 읽지 않기 때문에 별도 설정이 필요하다.
npm install --save-dev babel-jest @babel/preset-typescript ts-jest
// jest.config.js
module.exports = {
preset: 'ts-jest',
moduleNameMapper: {
'^@/(.*)$': '<rootDir>/src/$1',
},
};
moduleNameMapper로 tsconfig의 paths와 동일하게 맞춰줘야 한다.
정리
TypeScript cannot find module 에러는 딱 떨어지는 단일 원인이 아니다. 발생 맥락을 보고 위 패턴 중 어디에 해당하는지 진단하는 게 먼저다. --traceResolution으로 탐색 경로를 직접 확인하면 대부분 30분 안에 해결된다.
작성일: 2026-06-26