npm v12가 7월에 출시됩니다 — 무엇이 깨질 것이며 지금 어떻게 해결해야 하는가
요약
npm v12 출시와 함께 보안 강화를 위해 설치 스크립트, Git 의존성, 원격 타르볼이 기본적으로 차단됩니다. 이로 인해 네이티브 모듈 컴파일 실패 등 CI 환경에서 조용한 오류가 발생할 수 있으므로 사전 대비가 필요합니다.
핵심 포인트
- npm v12는 보안을 위해 allow-scripts, Git deps, remote tarballs를 기본 차단함
- 네이티브 모듈 미컴파일 시에도 npm ci가 성공(exit 0)할 수 있어 주의 필요
- npm 11.16.0+ 버전에서 미리 경고를 확인하고 마이그레이션을 준비할 것
- CI 파이프라인에 네이티브 모듈 존재 여부를 확인하는 스모크 테스트 추가 권장
요약(TL;DR): npm v12는 CI(지속적 통합)를 조용히 망가뜨릴 세 가지 기본 설정을 변경합니다: 설치 스크립트(install scripts) 비활성화, Git 의존성(Git deps) 차단, 원격 타르볼(remote tarballs) 차단. 네이티브 모듈(native modules)이 전혀 컴파일되지 않았음에도 npm ci가 종료 코드 0으로 성공할 수 있습니다. 여기 복사해서 바로 사용할 수 있는 마이그레이션 계획이 있습니다.
───
전체적인 그림 (The Big Picture)
12년 동안 npm은 의존성 트리(dependency tree) 내의 어떤 패키지라도 npm install 중에 임의의 코드를 실행할 수 있도록 허용해 왔습니다. postinstall 스크립트가 포함된 단 하나의 탈취된 패키지만으로도 환경 변수, SSH 키, .npmrc 토큰을 유출할 수 있었습니다. Shai Halud 공급망 공격(supply-chain attack)은 이를 무시할 수 없게 만들었습니다.
pm v12는 마침내 이 문제를 해결합니다. 하지만 이 해결책에는 고통이 따릅니다:
스크립트가 기본적으로 꺼져 있음 — allowScripts 기본값이 off로 설정됩니다. 네이티브 모듈 (bcrypt, sharp, esbuild, node-gyp)이 컴파일되지 않습니다.
Git 의존성이 차단됨 — --allow-git 기본값이 none으로 설정됩니다. 모노레포(Monorepo) 내부 참조, 포크(forks), 프라이빗 저장소 의존성 등이 모두 차단됩니다.
원격 URL 의존성이 차단됨 — --allow-remote 기본값이 none으로 설정됩니다.
원치 않더라도 v12를 사용하게 될 것입니다. Node.js는 npm을 번들로 포함합니다. LTS 버전(22, 24, 26)이 v12 번들을 채택하면, 여러분의 CI 파이프라인과 개발 환경의 동작이 갑자기 달라질 것입니다.
좋은 소식: npm 11.16.0+ 버전부터 이미 경고를 표시합니다. 오늘 바로 준비할 수 있습니다.
───
조용한 살인자: 앱은 고장 났는데 npm ci는 성공할 수 있음
이것이 v12에서 가장 위험한 부분이며, 팀들을 방심하게 만듭니다:
$ npm ci # 종료 코드 0으로 종료 ✅
$ npm test # 통과 ✅
$ node app.js # 💥 'bcrypt' 모듈을 찾을 수 없습니다
pm v12의 npm ci는 스크립트가 차단되었을 때 실패하지 않고, 단지 조용히 스크립트를 건너뜁니다. 네이티브 모듈은 전혀 컴파일되지 않았지만, CI는 초록불(성공)이 뜹니다. 앱은 런타임(runtime)에 충돌합니다.
해결책: 모든 npm ci 이후에 스모크 테스트(smoke test)를 추가하세요:
node -e "
const pkgs = ['sharp', 'esbuild', 'bcrypt'];
for (const p of pkgs) {
try { require(p); console.log('✓', p); }
catch(e) { console.error('✗', p, '— 컴파일되지 않음 (NOT COMPILED)'); process.exit(1); }
}
console.log('모든 네이티브 모듈이 존재합니다');
"
───
마이그레이션 계획 (15분 소요)
마이그레이션 계획 (15분 소요)
1단계: npm 11.16.0+로 업그레이드 (경고 모드, 아직은 아무것도 깨지지 않음)
npm install -g npm@11
2단계: 무엇이 차단될지 확인하기
npm install
다음과 같은 경고가 표시됩니다:
npm warn allow-scripts 8 packages have install scripts not yet covered
npm warn allow-scripts Run npm approve-scripts --allow-scripts-pending to review
3단계: 감사(Audit) 및 승인
스크립트를 실행하는 모든 패키지 목록 표시
npm approve-scripts --allow-scripts-pending
신뢰할 수 있는 패키지 승인 (대부분의 프로젝트는 3~8개 정도임)
npm approve-scripts bcrypt sharp node-gyp
나머지는 거부 (package.json에 기록됨 — 이를 커밋하세요)
npm deny-scripts
4단계: 트리 내에 숨겨진 Git 의존성 찾기
grep -r "git+" package.json package-lock.json
npm ls --all | grep -E "(git+|https://.*.tgz)"
의외의 결과가 나올 수 있습니다 — 간접 의존성 (transitive dependencies)이 Git 참조를 가져오는 경우가 많기 때문입니다. 만약 발견한다면:
빠른 해결책: .npmrc에 추가
echo "allow-git=true" >> .npmrc
더 나은 해결책: 레지스트리 버전으로 마이그레이션
5단계: npm-shrinkwrap.json 확인 (v12에서는 삭제됨)
ls npm-shrinkwrap.json 2>/dev/null && mv npm-shrinkwrap.json package-lock.json
6단계: npm view --json 파싱 수정
v12에서는 npm view --json이 항상 배열(arrays)을 반환하도록 변경됩니다. 만약 CI 스크립트가 다음과 같이 작성되어 있다면:
npm view lodash version --json | jq -r '.version'
이 부분은 깨지게 됩니다. 수정 방법:
npm view lodash version --json | jq -r '.[0]'
───
GitHub Actions: 프로덕션 준비 완료 워크플로우 (Production-Ready Workflow)
다음은 npm v12를 위한 완전한 CI 워크플로우입니다:
name: CI — npm v12 Compatible
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node: [18, 20, 22, 24]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
...
───
Docker: C++17을 사용한 멀티 스테이지 (Multi-Stage)
npm v12는 네이티브 모듈 (native modules)을 위해 C++17을 요구합니다. gcc 7이 포함된 기존 Docker 이미지는 충분하지 않을 것입니다.
FROM node:22-slim
npm v12는 C++17 툴체인이 필요함
RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential python3 make gcc g++ \
&& rm -rf /var/lib/apt/lists/*
RUN npm install -g npm@12
WORKDIR /app
COPY package.json package-lock.json ./
설치 + 승인 + 검증
RUN npm ci --allow-scripts-pending && \
npm approve-scripts node-gyp sharp esbuild && \
node -e "require('sharp'); require('esbuild'); console.log('Native modules OK')"
COPY . .
EXPOSE 3000
CMD ["node", "index.js"]
───
지금 업그레이드해야 할까요?
| 시나리오 | 조치 |
|---|---|
| 순수 JS 프로젝트 (네이티브 의존성 없음) | 지금 업그레이드하세요 — 5분이면 해결됩니다 |
| ... | |
| ─── |
결론
npm v12는 "업그레이드해야 할까요?"의 문제가 아닙니다. "언제 나에게 닥칠 것인가?"의 문제입니다. Node.js가 이를 번들링할 것이고, 여러분의 CI (지속적 통합) 환경이 이를 상속받을 것이며, 지금 준비하지 않는다면 여러분의 배포는 최악의 타이밍에 중단될 것입니다.
대부분의 프로젝트에서 마이그레이션 (Migration)에는 15분이 소요됩니다. 하지만 이를 통해 방지할 수 있는 서비스 중단 시간은 15시간의 가치가 있습니다.
───
이 가이드는 npm 11.16.0+ 동작 방식과 공식 npm v12 발표를 기반으로 작성되었습니다. 더 자세한 내용은 InstallSafe.dev를 확인하세요. 이곳은 FAQ, CI/CD 템플릿, 그리고 npm 11과 12의 상세 비교를 제공하는 무료 npm v12 마이그레이션 가이드입니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기