npm 의존성과 빌드 에러: 정확히 이해하기
프로젝트에서 사용하는 패키지가 삭제되면 어떤 문제가 생길까요? dependency chain을 따라가며 정확히 알아보겠습니다.
📦 상황 설명
프로젝트 구조를 가정해보겠습ㄴ니다.
my-project (우리 프로젝트)
└─ common-library (git dependency)
└─ common-formatter (common-library의 dependency)
package.json에서 common-library를 가져오고 있는데, 그 안에common-formatter가 있다. 이게 만약 없어지면 my-project에도 영향이 갈까?
🔍 실제로 사용하는지 확인하기
먼저 코드에서 실제로 사용하는지 검색해봤습니다:
{
"dependencies": {
"common-formatter": "^1.8.0"
}
}
# common-library 내부에서 사용
- common-library/plugins/formatter.ts ← import해서 사용
- common-library/filters/formatter.ts ← Vue 필터로 등록
하지만 my-project 코드에서는 전혀 사용하지 않았습니다:
# 검색 결과
$formatter → 0건
| formatCurrency → 0건
import 'common-formatter' → 0건
✅ 런타임 영향: 없음
실제로 사용하지 않으므로 런타임에는 아무 영향이 없습니다.
my-project의 nuxt.config.ts를 확인해본 결과:
// my-project/nuxt-configs/plugins.ts
export const plugins = [
'@/plugins/vue-placeholders.js',
'@/plugins/initialize-locale.ts',
'@/plugins/bootstrap.ts',
// formatter 관련 플러그인 없음!
];
common-library의 formatter 플러그인을 등록조차 하지 않았습니다. 완전히 독립적으로 운영되고 있었어요.
🤔 그럼 빌드는? npm install은?
여기서 중요한 질문이 나옵니다. "그래도 npm install 할 때는 문제 생기는 거 아니야?"
npm 의존성의 3단계
package.json에 있으면 무조건 설치됨
→
common-formatter도 node_modules에 설치됨 Layer 2: 등록 단계 (nuxt.config.ts)
plugins 배열에 등록된 것만 로드
→ formatter 플러그인 등록 안 됨
Layer 3: 사용 단계 (import)
실제로 import한 코드만 번들에 포함
→ formatter import 없음
즉, 설치는 되지만 사용하지 않는 상태입니다.
⚠️ npm install이 실패하는 경우
하지만 여기서 문제가 있습니다. 다음 상황이 되면 어떻게 될까요?
시나리오:
1. common-library는 여전히 package.json에 common-formatter를 dependency로 가지고 있음
2. 하지만 common-formatter 패키지가 삭제됨
3. npm install 실행
결과:
❌ npm ERR! 404 Not Found - GET https://registry.npmjs.org/common-formatter
❌ npm ERR! 'common-formatter' is not in the npm registry
❌ 빌드 파이프라인 전체 실패
실제로 사용하지 않아도 npm install이 실패합니다!
📊 시나리오별 정리
| 상황 | npm install | 빌드 | 런타임 |
|---|---|---|---|
| 현재 상태 (패키지 존재) | ✅ 성공 | ✅ 성공 | ✅ 정상 |
| common-library가 새 버전에서 제거 | ✅ 성공 | ✅ 성공 | ✅ 정상 |
| common-formatter 패키지가 삭제됨 (common-library는 변경 없음) |
❌ 실패 | ❌ 불가능 | ❌ 도달 불가 |
🔧 실제 확인 방법
최신 버전에서도 여전히 dependency가 있는지 확인:
# common-library의 최신 버전 확인
$ npm view common-library versions --json
[
"1.0.0",
"1.0.1",
"1.0.2",
"1.0.3"
]
# 최신 버전의 dependencies 확인
$ npm view common-library@1.0.3 dependencies
{
"common-formatter": "^1.8.0"
}
최신 버전에도 여전히 포함되어 있네요!
😅 추가 발견: common-library는 관리가 안 되고 있었습니다
실제 상황
common-library는 관리가 안 되고 있는 레거시 패키지였습니다. 이런 경우 리스크가 있습니다.
관리 안 되는 dependency의 위험성
- 다른 팀이 "common-formatter 안 쓰니까 패키지 삭제해야지"
- npm registry에서 unpublish 또는 deprecated 처리
- common-library는 관리 안 되니까 package.json 그대로
- CI/CD 파이프라인 또는 새로운 환경에서 npm install 실행
- 전체 빌드 시스템 마비
💡 대응 방안
Option 1: 선제적 대응 (추천)
// common-library dependency 제거
// 필요한 코드만 우리 프로젝트로 복사
// 완전한 독립성 확보
장점: 외부 영향 완전 차단, 컨트롤 가능
단점: 초기 작업 필요 (하지만 어차피 업데이트 안 받으니까 문제없음)
Option 2: 방어적 대응
// package.json에서 common-library를 fork하여 관리
{
"dependencies": {
"common-library": "file:./local-packages/common-library"
}
}
// 또는 private registry 사용
{
"dependencies": {
"common-library": "1.0.3"
}
}
장점: 문제 발생 시 빠른 대응
단점: 문제가 터질 때까지 기다려야 함
Option 3: 모니터링
# 주기적으로 패키지 존재 여부 확인
npm view common-formatter
# 또는 package-lock.json을 git에 커밋하여 고정
장점: 당장 작업 없음
단점: Reactive 대응, 긴급 상황 가능성
📝 핵심 정리
Q: 사용하지 않는 dependency가 제거되면 영향이 있나요?
런타임 영향: ❌ 없음 (사용하지 않으므로)
빌드 영향: ❌ 없음 (import하지 않으므로)
npm install 영향: ⚠️ 있을 수 있음!
- 상위 패키지(common-library)가 여전히 dependency로 가지고 있으면
- 해당 패키지가 삭제되거나 접근 불가능해지면
- npm install이 실패합니다
- 실제로 사용하지 않아도 설치 시도는 하기 때문입니다
🔍 Webpack/Nuxt 빌드 프로세스 이해하기
많은 분들이 헷갈려하는 부분인데, "설치된 패키지"와 "빌드에 포함되는 코드"는 다릅니다:
빌드 과정 단계별 분석
1️⃣ npm install 단계
└─ package.json의 모든 dependencies 설치
└─ common-formatter도 node_modules에 설치됨
└─ ⚠️ 이 단계에서 패키지가 없으면 에러!
2️⃣ Webpack 분석 단계
└─ entry point부터 import 구문 따라가기
└─ nuxt.config.ts의 plugins 확인
└─ 실제로 import된 모듈만 수집
3️⃣ 번들링 단계
└─ 2단계에서 수집된 코드만 번들에 포함
└─ common-formatter는 import 안 했으므로 제외
└─ Tree-shaking으로 최적화
4️⃣ 최종 빌드 결과
└─ dist/에는 실제 사용한 코드만 포함
└─ 번들 크기 최소화
즉, node_modules에 있다고 해서 최종 빌드에 포함되는 게 아닙니다. import하지 않은 코드는 번들에서 제외됩니다.
🎯 결론
의존성 관리에서 중요한 교훈:
- "사용하지 않음" ≠ "영향 없음" - npm install 단계에서 여전히 영향 받음
- Transitive dependency의 위험성 - 직접 사용하지 않아도 간접 의존성이 문제가 될 수 있음
- 관리 안 되는 dependency는 기술 부채 - 언제든 터질 수 있는 시한폭탄
- 외부 dependency는 신중하게 - 특히 관리 주체가 불분명한 경우 더욱 위험
- package-lock.json의 중요성 - 정확한 버전을 고정하여 예상치 못한 변경 방지
최종 권장사항: 관리 안 되는 외부 패키지에 의존하기보다는, 필요한 코드를 직접 관리하거나 확실히 관리되는 패키지를 사용하는 것이 안전합니다. 특히 레거시 프로젝트에서는 의존성 최소화가 장기적인 안정성에 도움이 됩니다.
참고: 이 글은 실제 프로젝트 경험을 바탕으로 작성되었으며, 패키지 이름과 경로는 예시입니다. npm과 Nuxt.js 기반 프로젝트를 기준으로 작성되었지만, 다른 패키지 매니저(yarn, pnpm)나 빌드 도구에도 동일한 원리가 적용됩니다.
'Frontend > Etc' 카테고리의 다른 글
| code CERT_HAS_EXPIRED, request to https://registry.npm.taobao.org/nuxi failed (1) | 2024.10.13 |
|---|---|
| (작성중)Node-fetch vs Axios vs Isomorcphic-fetch vs Ofetch (1) | 2024.10.09 |
| pnpm (0) | 2024.10.07 |
| Open Api Specification (2) | 2024.10.07 |