본문 바로가기
[AWS-FRF]/CICD

RUN npm install 이란?

by METAVERSE STORY 2025. 11. 4.
반응형

 

 

npm install은 package.json에 정의된 의존성들을 설치해 node_modules를 만드는 명령입니다. 컨텍스트에 따라 로컬 개발, CI, Docker 이미지 빌드 등에서 동작과 권장 사용법이 다릅니다.


1) 기본 동작 (터미널에서)

 
npm install
  • package.json의 dependencies와 devDependencies를 읽어서 node_modules에 패키지들을 설치.
  • package-lock.json(또는 npm-shrinkwrap.json)이 있으면 잠금 파일을 참고해 정확한 버전으로 설치하려고 시도(동일한 트리 재현).
  • 설치 후 package-lock.json이 없으면 자동으로 생성/업데이트됨.

추가 옵션:

  • npm install <pkg> : 특정 패키지 설치 (로컬).
  • npm install -g <pkg> : 전역 설치.
  • --save / --save-dev : 예전에는 필요했지만 최신 npm은 기본으로 dependencies에 추가. --save-dev는 개발용으로 devDependencies에 추가.
  • --save-exact : 정확한 버전(=)으로 저장.
  • --no-optional : optionalDependencies 설치 안 함.
  • --only=production 또는 NODE_ENV=production npm install : devDependencies 제외(프로덕션 빌드).
  • --legacy-peer-deps : peer dependency 충돌 무시(일부 최신 npm에서 필요).
  • --silent / --no-audit 등 로그/감사 무시 옵션들.

실행 결과:

  • node_modules/ 생성(혹은 업데이트)
  • package-lock.json 생성/수정
  • postinstall / 기타 lifecycle 스크립트(예: 빌드, 바이너리 설치) 실행

2) npm install vs npm ci

  • npm install : 유연. package-lock.json이 있어도 package.json의 범위에서 필요한 변경을 할 수 있고 잠금파일을 업데이트할 수 있음.
  • npm ci : CI 및 재현 가능한 빌드용. package-lock.json이 없으면 실패. node_modules를 삭제하고 잠금파일에 정확히 맞춰 설치(더 빠르고 안정적).
    • 권장: CI, Docker 프로덕션 이미지 빌드시 npm ci --only=production 사용.

3) Dockerfile에서의 사용(권장 패턴)

Docker 이미지 빌드시 캐시 활용과 이미지를 작게 만드는 것이 중요합니다.

권장 Dockerfile(예시):

 
FROM node:20-alpine AS builder
WORKDIR /app

# package.json, package-lock.json만 먼저 복사 (의존성 변경 시에만 레이어 재설치)
COPY package*.json ./

# CI 스타일 설치 (devDependencies 포함해서 빌드 필요시)
RUN npm ci

# 앱 소스 복사 및 빌드
COPY . .
RUN npm run build

# 프로덕션 이미지 (멀티스테이지)
FROM node:20-alpine AS runner
WORKDIR /app

ENV NODE_ENV=production

# package.json/lock만 복사해서 프로덕션 의존성만 설치
COPY package*.json ./
RUN npm ci --only=production

# 빌드 산출물 복사
COPY --from=builder /app/dist ./dist

# 사용자 권한 변경 (root 대신 비루트 권장)
USER node
CMD ["node", "dist/index.js"]
 
 

핵심 포인트:

  • COPY package*.json ./ 먼저 해서 의존성 설치가 코드 변경마다 재실행되는 것을 방지(레이어 캐싱).
  • 빌드 단계와 런타임 단계를 분리(멀티스테이지)해 런타임 이미지 크기 축소.
  • npm ci 사용: 재현성 보장, 빠름.
  • NODE_ENV=production 설정으로 devDependencies 설치 방지.
  • 가능하면 non-root 유저로 실행.

4) 성능/용량 최적화 팁

  • npm ci --only=production으로 devDependencies 제외.
  • --no-optional로 optionalDependencies 제거.
  • npm pack + 복원 방식(특수 상황)으로 필요 패키지만 포함.
  • node_modules를 이미지에 모두 넣지 않고 빌드 산출물(번들, transpile 결과)만 포함.
  • npm prune --production으로 dev 의존성 제거(로컬에서 실수로 설치했을 때).
  • 캐시: CI에서 npm 캐시 경로를 캐싱하면 설치 속도 향상 (~/.npm).

5) 보안 및 감사

  • npm audit : 취약점 검사
  • npm audit fix : 자동 패치 시도(주의: 자동 변경이 생길 수 있음)
  • 프로덕션에서는 자동 업그레이드 / 패치 전에 테스트 필수.

6) 자주 발생하는 오류와 해결 방법

  1. EACCES (권한 오류)
    • 원인: 글로벌 설치 시 패키지 디렉터리 권한 문제.
    • 해결: sudo 사용(권장 X), npm 글로벌 디렉토리 변경, 또는 nvm 사용으로 사용자 권한 관리.
  2. ENOSPC / ENOMEM (디스크/메모리 부족)
    • 원인: 디스크 공간 부족 또는 메모리 부족(특히 Docker 빌드).
    • 해결: 디스크 정리, 도커 빌드에 더 많은 메모리 할당.
  3. network timeout / 504 / registry errors
    • 원인: 네트워크/프록시/회사 방화벽.
    • 해결: npm config set registry https://registry.npmjs.org/ 재설정, 프록시 설정, 사내 레지스트리(Artifactory, Nexus) 사용.
  4. peer dependency conflicts
    • 원인: 라이브러리 간 peerDependencies 불일치.
    • 해결: 버전 맞추기, --legacy-peer-deps로 임시 회피, 장기 해결은 패키지 버전 조정.
  5. postinstall 실패 (빌드 스크립트 실패)
    • 원인: 네이티브 빌드 도구(심볼릭, node-gyp) 또는 환경변수 누락.
    • 해결: 필요한 빌드툴(파이썬, make, g++ 등) 설치, 환경 설정.

7) package-lock.json의 중요성

  • 동일한 의존성 트리를 재현하려면 반드시 커밋하고 사용.
  • CI와 프로덕션 빌드에서는 npm ci + package-lock.json이 필수적.

8) 라이프사이클 훅 (설치 과정에 실행되는 스크립트)

  • preinstall → install → postinstall → prepublishOnly 등.
  • 패키지에 따라 설치 시 빌드나 바이너리 다운로드가 트리거될 수 있음(예: node-sass, sharp).

9) 실용 예제 (로컬에서 프로덕션 설치)

 
# 프로덕션 환경에서 devDependencies 없이 설치 NODE_ENV=production npm install # 또는 npm install --only=production

10) 요약된 권장사항

  • 로컬 개발: npm install (혹은 npm ci로 잠금파일 기반 재현 설치)
  • CI/빌드: npm ci
  • Docker 프로덕션 이미지: 멀티스테이지 + npm ci --only=production + package*.json 먼저 복사
  • 항상 package-lock.json 커밋
  • 오류 발생 시 로그(에러 메시지) 보고 권한/네트워크/메모리/peer-deps 순으로 점검

 

 

 

반응형

댓글