npm install과 npm ci 차이
이번에 자동화 파이프라인을 다시 작성하게 되었습니다. 작성하면서 npm install과 npm ci의 차이점에 대해 이해하게 되었습니다.
사용하여 빌드환경에 의존성을 설치합니다. 이때 의존성이 기존 프로젝트와 동일한 환경에서 동작하게 하기 위해 우리는 package.json파일을 통해 의존성 관리를 합니다. 이번 포스팅에는 의존성관리를 꼭 해야하는 이유와 npm install과 npm ci의 차이, dependencie 환경과 devDependencies환경의 차이에 대해 정리하였습니다.
의존성 관리란? 프로젝트에서 사용하는 외부 라이브러리의 버전, 설치 위치, 그리고 호환성을 일관되게 관리하는 작업을 말합니다.
특히 Node.js 생태계에서는 npm을 통해 수많은 라이브러리를 설치하고 버전을 지정하는 작업이 필수적지만 협업 환경이나 자동화된 빌드·배포 환경에서 의존성 관리를 제대로 하지 않으면 여러 가지 문제에 직면할 수 있습니다.
( 제 컴퓨터에서는 되는데요? 와 같은 문제..✩ )
의존성 관리를 해야하는 이유!
의존성 관리는 해야하는 이유는 협업에서나 CICD 자동화 작업에서 예상치 못한 에러를 방지하기 위해서 필수적입니다.
- 협업 안정성 : 팀원마다 설치된 패키지 버전이 다르면, 특정 환경에서만 재현되는 예기치 못한 에러가 발생할 수 있습니다.
- CI/CD 일관성 : 자동화된 빌드·배포 파이프라인에서 개발 환경과 완벽히 동일한 설치 결과를 보장해야만, 워크플로우가 안정적으로 동작합니다. 의존성 관리를 통해 “로컬에서 빌드된 번들”과 “서버에서 빌드된 번들”이 똑같은 상태로 유지됩니다.
- 효율성 증대 : 캐시( GitHub Actions의 actions/cache와 같은 도구 )를 활용하면, 변경된 의존성만 설치하고 불필요한 다운로드를 피할 수 있어 빌드 시간을 크게 단축할 수 있습니다.
- 보안·무결성 확보 : 의존성 버전을 명시적으로 고정하고 검증하면, 악의적인 패키지 변경(tampering)이나 취약점 업데이트 적용 누락을 방지할 수 있습니다.
- 정확한 롤백·디버깅 : 특정 시점의 의존성 스냅샷을 저장해 두면, 문제가 생겼을 때 과거 상태로 쉽게 되돌아가서 원인을 조사할 수 있습니다.
npm install vs npm ci
| npm install | npm ci | |
|---|---|---|
| 의존성 기준 | package.json 중심, 락파일 참고 | package-lock.json 엄격 고정 |
| node_modules 처리 | 변경된 부분만 업데이트 | 전체 삭제 후 재설치 |
| 속도 | 변경된 부분만 설치, 느릴 수 있음 | 병렬 설치로 보통 더 빠름 |
| 재현성 | 락파일이 바뀌면 설치 결과 변경 가능 | 락파일 기준 100% 동일 설치 |
| 락(package-lock.json etc)파일 필요 여부 | 선택적 | 필수 |
| 사용 권장 환경 | 로컬 개발 | CI/CD 자동화 환경 |
npm install
Node.js 프로젝트에서 사용되는 의존성 설치 명령어, 프로젝트 폴더 내의 package.json 파일을 참조하여 필요한 패키지를 다운로드하고 node_modules 폴더에 설치합니다. 만약 package-lock.json 같은 락 파일이 있다면 이를 참고하여 버전을 최대한 맞추려 노력하지만, 엄격히 고려하지는 않습니다.
프로젝트 작업 중 로컬에서 새로운 라이브러리를 추가하거나 버전을 바꾸고자 할 때 주로 사용합니다. 이때 package.json과 package-lock.json은 자동으로 업데이트되고, 이 과정에서 간혹 버전이 변경되어 package.json 파일 내 명시된 버전이 변경되는 경우가 발생합니다.
npm install은 변경된 부분만 설치하고 기존 설치된 패키지는 그대로 둬서 빠른 작업이 가능하도록 설계되었습니다.
npm install <설치하려는 라이브러리>
npm install --save-dev jest (-D 옵션 사용 시 개발용 의존성에 추가)
npm ci
npm ci의 ci는 Continuous Integration(지속적 통합)이란 뜻으로 주로 package-lock.json으로 고정된 필요한 의존성 상태를 설치한다거나 파이프라인 자동화 환경에서 빌드, 배포 목적으로 사용되는 명령어입니다.
npm ci의 특징
- 반드시 package-lock.json이 있어야 하며, 이 파일에 명시된 버전으로 정확하게 설치합니다.
- 설치 전에 node_modules 폴더를 완전히 삭제하고, 락 파일 기준으로 의존성을 새로 설치합니다.
- 병렬 설치와 캐시 활용 덕분에 속도가 빠릅니다.
- 결과적으로 모든 빌드 환경에서 동일한 의존성 트리가 보장되어, 배포·테스트 과정에서 예기치 못한 문제를 줄입니다.
GitHub Actions나 Jenkins 와 같은 CI/CD 환경에서는 npm ci가 권장됩니다.
npm 주요 옵션과 역할
-D 혹은 --save-dev 옵션
개발할 때만 필요한 도구들(테스트 프레임워크, 린터, 빌드 도구 등)은 devDependencies에 추가합니다. 이렇게 하면 프로덕션 빌드 시 필요 없는 의존성을 제외할 수 있어 효율적입니다.
npm install --save-dev jest 혹은 npm i -D jest
--no-save 옵션
이 옵션은 node_modules에만 임시로 패키지를 설치하고, package.json과 package-lock.json은 전혀 변경하지 않습니다. 주로 CI 환경에서 일시적으로만 패키지가 필요할 때 사용합니다.
npm install --no-save rss-parser
GitHub Actions 실행 환경 이해하기
GitHub Actions 워크플로우는 기본적으로 깨끗한 가상 머신(VM) 위에서 매번 새로 실행됩니다. 따라서 node_modules 같은 폴더는 항상 초기 상태이며, 매번 의존성을 전부 새로 설치해야 합니다.
GitHub Actions의 actions/cache를 이용한 효율적인 캐시
GitHub Actions는 actions/cache 액션을 통해 이전 빌드에서 설치한 의존성 파일을 압축해서 GitHub의 전용 스토리지에 저장합니다. 이후 빌드에서 같은 키를 가진 캐시가 있다면 이를 내려받아 설치 시간을 대폭 줄입니다.
- 캐시 저장 위치: GitHub가 제공하는 글로벌 스토리지
- 복원 과정: 저장된 압축본을 풀어서 node_modules 혹은 ~/.npm 등으로 복원
- uses: actions/cache@v3
with:
path: ~/.npm
key: ${{ runner.os }}-npm-${{ hashFiles('\*\*/package-lock.json') }}
restore-keys: |
${{ runner.os }}-npm-
dependencies와 devDependencies 의 차이
개발, 테스트 환경에서만 쓰이는 도구는 devDepandencies에 설치하고 프로덕션 환경에서 꼭 필요한 라이브러리는 dependencies에 설치합니다.
dependencies
- 프로덕션 환경에서 반드시 필요한 라이브러리
- React, Express 등
devDependencies
- 개발 및 테스트 환경에서만 필요한 도구
- Jest, ESLint, Babel 등
npm install을 했을 때 dependencies와 devDependencies의 설치 동작 차이
- npm install은 package.json에 기록된 dependencies와 devDependencies 모두를 설치
- 프로덕션 빌드 시(NODE_ENV=production 혹은 npm install --production)에는 devDependencies가 설치되지 않습니다.
devDependencies와 dependencies를 구분하는 이유
devDependencies와 dependencies를 구분하는 이유는 빌드를 할 때 배포 시 불필요한 개발 도구가 포함되지 않도록 분리하여 프로덕션 환경에서 용량과 보안성 강화할 수 있습니다.
- dependencies: 실제 서비스(프로덕션)에서 애플리케이션이 동작하는 데 반드시 필요한 라이브러리를 포함합니다. React, Express 같은 런타임에 필수적인 패키지가 여기에 포함됩니다.
- devDependencies: 개발·테스트·빌드 과정에서만 필요한 도구들입니다. 테스트 프레임워크(Jest), 코드 린터(ESLint), 빌드 도구(Webpack)가 여기에 속합니다. 프로덕션 빌드 시에는 보통 설치하지 않아 용량을 줄이고 보안을 강화할 수 있습니다.
마무리
이전까지 npm ci와 npm install의 차이를 모르고 있었다거나 devDependencies나 dependencies의 차이를 몰랐다면 이번 포스팅을 통해 기존 프로젝트 package.json 수정해 보는 것도 추천드립니다! 다음 포스팅에서는 간단한 GitHub Actions를 이용한 Tistory 포스팅 GitHub Commit 기록하기에 관한 가이드도 작성해 보겠습니다.
참고 사이트
추가 질문이나 작성 내용에 오류가 있다면 언제든지 댓글로 남겨주세요!
'DevOps.' 카테고리의 다른 글
| GitHub Actions로 Tistory 게시물 커밋 남기기 ( JavaScript ) (3) | 2025.06.14 |
|---|---|
| fatal: the remote end hung up unexpectedly 오류 해결 (0) | 2024.09.09 |
| GitHub Actions Workflow 명령어 정리 (0) | 2024.09.09 |