DevOwen
package.json을 관리하는 방법
Val Town(node_modules 863MB) 팀의 의존성 위생. 소스 읽기 · 전이 의존성 파악 · 벤더링 · Renovate/Knip 까지 현실적인 루틴을 한 세트로.
핵심 요약
저자의 루틴 6단계:
- 새 의존성은 소스 코드를 읽는다 (리액트급 메가 의존성은 예외). README 만으로는 실제 구현/보안 표면을 알 수 없음
- 50줄 미만은 NPM 대신 벤더링(vendoring) — 코드를 프로젝트로 복사하고 오픈소스 라이선스를 주석으로 남김
npm ls/pnpm why로 전이 의존성 확인 — 이미 있는 것을 재사용- 패키지 실제 크기 분석 —
node_modules는 Grand Perspective, 번들은rollup-plugin-visualizer/ Next.js bundle analyzer - Renovate 로 점진 업그레이드 + Knip 으로 사용하지 않는 의존성/파일 제거 — 연 1회 대규모 업그레이드 금지
- 신뢰 가능한 저자 치트시트 유지 — Promise 계열은 Sindre Sorhus, 마크다운은 unified, 차세대 Node 는 unjs, 트랜스파일러는 Rich Harris
핵심 규칙: '좋은 모듈 = 유지보수 이력 + 빌트인 TS 타입 + 통과하는 테스트 + 좋은 문서' → 실력의 분위기(vibes of competence).
package.json 은 '내가 직접 설치한 것' 만 보여주는 빙산의 일각. 실제 node_modules 를 채우는 건 전이 의존성(transitive deps) 이다. package-lock.json / pnpm-lock.yaml 을 읽는 습관이 PageRank 처럼 생태계 지도를 머릿속에 만든다.
'의존성 많으면 나쁘다' 는 조급한 결론은 실무를 망친다. 저자 기준으로는:
- 본질적 복잡성(essential complexity) 이 있는 기능은 직접 구현 불가 (
codemirror, TypeScript 트랜스파일러) - 새 의존성을 추가할 때 실제 비용 = 직접 크기 + 전이 의존성 + 보안 표면
- 이미 전이적으로 설치된 의존성 을 활용하면 '공짜' 로 추가 가능 (
esbuild가 Vite/drizzle-kit/tsx 때문에 이미 있음)
이 감각이 있어야 '라이브러리 vs 직접 구현 vs 벤더링' 판단이 가능하다.
학습 포인트
면접 답변으로 연결할 학습 포인트입니다.
50줄짜리 의존성은 벤더링이 정답
전이 의존성 3개를 끌고 오는 gzip 2MB 모듈에서 내가 실제로 쓰는 건 50줄 이라면:
# 대신
mkdir -p src/vendor/tiny-queue
cp node_modules/tiny-queue/index.js src/vendor/tiny-queue/
# 상단에 라이선스 주석 추가
이득: (1) node_modules 경량화, (2) 전이 의존성의 보안 이슈가 내 빌드에 영향 없음, (3) CI 속도 향상.
라이선스를 지운 채 복사. MIT/BSD 등 라이선스 문구 유지는 법적 의무. 원본 저장소의 LICENSE 파일을 함께 복제한다.
`esbuild` 가 이미 있는데 또 설치하면 무료
pnpm 기준 예:
pnpm why esbuild
# vite, drizzle-kit, tsx 가 모두 esbuild 를 가리킴
# 최상위에 esbuild 를 선언해도 dedupe 로 같은 바이너리 참조
전이 의존성 재활용은 공짜 의존성 추가. 단, 메이저 버전이 다르면 dedupe 가 깨져 중복 설치된다.
직접 의존성 선언 없이 전이적으로만 쓰는 것. 상위 패키지가 내일 esbuild 를 뺄 수도 있어 본인이 사용한다면 직접 선언이 맞다.
Knip + Renovate = 연 1회 대규모 업그레이드 지옥 탈출
| 도구 | 역할 | 주기 |
|---|---|---|
| Renovate | 매 PR 단위 의존성 업그레이드 제안 | 매일 / 매주 |
| Knip | package.json 에만 있고 실제 import 되지 않은 의존성·파일 탐지 | 수시 / CI |
npx knip
# Unused dependencies (3)
# lodash package.json
# moment package.json
둘을 함께 쓰면 의존성 그래프가 점진적으로 가벼워짐. 대규모 업그레이드는 정치적 비용이 크다 — 점진 개선이 실제로 더 싸다.
Renovate PR 을 쌓아두는 것. 한 달만 밀려도 수십 개가 쌓여 그 자체가 큰 업그레이드 가 됨. Auto-merge 정책을 설정하거나 주간 리뷰 시간 확보.
읽는 순서
- 1이론
npm/pnpm/yarn 의 lockfile 구조 차이 를 정리하고, dedupe 규칙이 어떻게 다른지 비교.
- 2구현
현재 프로젝트에
knip을 돌려 불필요 의존성 리스트를 뽑고, 상위 5개를 벤더링 또는 삭제. - 3실무
Renovate 를 도입하거나 이미 있다면 자동 머지 정책 점검. 매 월
npm audit/pnpm audit리포트도 함께. - 4설명
'의존성은 많을수록 나쁜가?' 질문에 '본질적 복잡성 vs 우발적 복잡성' 프레임으로 답해 본다.
면접 연결 질문
[감점 답변] 'npm install 후 테스트'. [좋은 답변] (1) 소스 규모 확인 — 50줄 미만이면 벤더링 고려, (2) pnpm why <pkg> 로 이미 있는지 확인, (3) 전이 의존성 수와 gzip 번들 사이즈, (4) 유지보수 이력/TS 타입/테스트/문서 4축, (5) 신뢰할 만한 저자인지(Sindre, isaacs, unjs 등).
[감점 답변] '별점 낮으면 나쁘다'. [좋은 답변] (1) 잘못된 문제를 해결 — 내 문제를 모듈에 맞추려면 나쁜 모듈, (2) 방치된 이슈 트래커, (3) TS 타입 부재/부정확, (4) 테스트 없음, (5) 문서가 예제 수준에 머무름. Depreciation 경고는 Knip/npm audit 에서 자동 탐지.
자기 점검
package.json 만 보면 충분하다는 오해. 실제 빌드/보안 표면은 전이 의존성 그래프 전체.