← 전체 글로 돌아가기

CI/CD

CI에서 npm install 대신 npm ci를 써야 하는 이유

npm ci는 package-lock.json을 기준으로 정확히 설치하고 일관성을 보장한다. CI 환경에서 npm install을 쓰면 lockfile과 달라진 패키지가 들어올 수 있다.

GitHub Actions에서 Node.js 프로젝트를 빌드할 때 npm install을 쓰는 경우가 있다. 로컬에서 쓰던 명령이라 익숙해서다. CI에서는 npm ci가 맞다. 차이가 있다.

npm install과 npm ci의 차이

npm installnpm ci
lockfile 기준package.json과 lockfile 모두 참조, 불일치 시 lockfile 업데이트package-lock.json 그대로 설치
lockfile 없을 때생성함에러로 종료
lockfile과 package.json 불일치lockfile을 수정해서 맞춤에러로 종료
node_modules 처리기존 디렉토리 유지, 증분 설치삭제 후 완전히 새로 설치

npm ci는 항상 node_modules를 지우고 다시 설치하기 때문에 이전 실행의 잔여물이 없다. 그리고 package-lock.json에 명시된 정확한 버전만 설치한다.

실제로 문제가 생기는 경우

로컬에서 npm install some-package를 실행하면서 package-lock.json이 업데이트됐는데, 이걸 커밋에 포함하지 않은 채 push하는 경우가 있다. CI에서 npm install을 쓰면 이 상황에서 조용히 다른 버전을 설치할 수 있다.

npm ci라면 lockfile과 package.json의 불일치를 감지해서 바로 에러를 낸다.

npm ERR! cipm can only install packages when your package.json and
npm ERR! package-lock.json or npm-shrinkwrap.json are in sync.

이 에러가 뜨면 로컬에서 lockfile을 올바르게 생성해서 다시 push해야 한다는 신호다.

GitHub Actions 설정 예시

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'  # node_modules 캐시

      - run: npm ci
      - run: npm run build
      - run: npm test

actions/setup-nodecache: 'npm'을 함께 쓰면 ~/.npm 캐시를 재사용해서 설치 속도를 높일 수 있다. npm cinode_modules를 지우지만 npm 글로벌 캐시는 유지하기 때문에 캐시와 함께 써도 문제없다.

로컬에서 npm ci를 쓰면 안 되나

써도 된다. 로컬에서 완전히 깨끗한 설치 상태로 테스트하고 싶을 때 유용하다. 다만 node_modules를 매번 지우기 때문에 개발 중에는 느리다. 일상적인 개발 중에는 npm install, CI에서는 npm ci가 실용적인 구분이다.