<aside> <img src="notion://custom_emoji/41b6b37a-cc38-4f0f-bb74-faede20facf4/153a054b-7d82-80e0-835a-007a795dfe1c" alt="notion://custom_emoji/41b6b37a-cc38-4f0f-bb74-faede20facf4/153a054b-7d82-80e0-835a-007a795dfe1c" width="40px" />
결론
npm ci
가 CI/CD에 적합합니다. CI/CD 환경에서는 재현 가능한 빌드(reproducible builds)가 가장 중요하다고 생각합니다. CI/CD라는 것 자체가 빠른 배포 주기를 달성하기 위함이고, 이 배포 주기의 단축에는 서비스의 신뢰성이 동반되어야 합니다. 그 신뢰성을 위해서는 언제 어디서나 빌드하더라도 정상 동작한다는 보장이 있어야 하고, 그게 바로 재현 가능한 빌드입니다.
서버는 그 소프트웨어를 구동하는 머신에서 사용하는 라이브러리 버전에 민감합니다(그래서 local에서는 되는데 서버에서는 안되는 상황이 종종 발생합니다). 따라서 그 재현 가능한 빌드를 위해서는 최대한 해당 소프트웨어를 구동하는 데 필요한 라이브러리 버전에 대해 변경을 최소화해야 하며 변경할 경우에는 충분한 테스트가 선행되어야 합니다.
따라서npm ci
는 정확한 버전을 설치하며, node_modules
을 초기화한 후 패키지를 다시 설치하기 때문에 일관성을 유지하고, 예기치 않은 패키지 변경을 방지할 수 있기 때문에 CI/CD에 적합합니다.
</aside>
https://docs.npmjs.com/cli/v6/using-npm/semver
표기 | 의미 | 가능한 버전 예시 | 불가능한 버전 예시 |
---|---|---|---|
1.2.3 |
정확히 1.2.3 버전만 | 1.2.3 | 1.2.4, 1.2.2 |
>1.2.3 |
1.2.3보다 큰 버전 | 1.2.4, 1.3.0, 2.0.0 | 1.2.3, 1.2.2 |
>=1.2.3 |
1.2.3 이상 버전 | 1.2.3, 1.2.4, 2.0.0 | 1.2.2, 1.1.0 |
<1.2.3 |
1.2.3보다 작은 버전 | 1.2.2, 1.1.0 | 1.2.3, 1.2.4 |
<=1.2.3 |
1.2.3 이하 버전 | 1.2.3, 1.2.2, 1.1.0 | 1.2.4, 2.0.0 |
1.2.3 - 2.3.4 |
1.2.3부터 2.3.4까지 (둘 다 포함) | 1.2.3, 1.5.0, 2.3.4 | 1.2.2, 2.3.5 |
1.2.x |
1.2.0 이상, 1.3.0 미만 | 1.2.0, 1.2.1, 1.2.99 | 1.3.0, 1.1.9 |
* |
모든 버전 | 0.0.1, 1.0.0, 99.99.99 | 없음 |
~1.2.3 |
패치 버전 업데이트만 허용 (≥1.2.3, <1.3.0) | 1.2.3, 1.2.4, 1.2.99 | 1.3.0, 1.1.0 |
^1.2.3 |
하위호환 업데이트만 허용 (≥1.2.3, <2.0.0) | 1.2.3, 1.3.0, 1.9.9 | 2.0.0, 1.2.2 |
^0.2.3 |
마이너 버전 고정 (≥0.2.3, <0.3.0) | 0.2.3, 0.2.4, 0.2.99 | 0.3.0, 0.2.2 |
^0.0.3 |
패치 버전 고정 (≥0.0.3, <0.0.4) | 0.0.3 | 0.0.4, 0.0.2 |
`1.2.3 | 2.3.4` | 1.2.3 또는 2.3.4 |
즉, npm install 시 설치되는 버전을 이러한 표기법으로 정의할 수 있다~ 정도로 넘어가면 된다.
파일명 | 역할 및 기능 |
---|---|
package.json | 프로젝트에서 사용하는 패키지와 버전을 정의하는 파일. 개발자가 직접 작성 및 수정 가능. Semantic Versioning(^ , ~ 등)을 사용하여 버전 범위를 지정할 수 있다. |
package-lock.json | package.json 을 기반으로 실제 설치된 패키지의 정확한 버전과 종속 관계를 기록하는 파일. npm install 또는 npm ci 실행 시 자동으로 생성 및 업데이트된다. |
package.json
: 개발자가 직접 수정 가능하며, 의존성을 추가하거나 버전 범위를 조정할 수 있다.package-lock.json
: 일반적으로 수동 수정하지 않으며, npm이 자동으로 관리한다.package-lock.json
은 프로젝트에서 실제 사용하는 패키지의 버전 정보를 기록하여 동일한 환경을 재현하는 역할을 한다.terraform.tfstate
는 현재 클라우드 인프라의 상태를 추적하고, 변경 사항을 적용할 때 이를 기준으로 비교하는 역할을 함.둘 다 현재 상태를 저장하고 일관성을 유지하는 역할을 한다는 점에서 비슷하다고 생각했습니다.
package-lock.json
은 CI/CD 환경에서 일관된 빌드를 보장하는 데 중요한 역할을 한다.package.json
을 사용하더라도 package-lock.json
이 다르면 실제 설치되는 패키지 버전이 달라질 수 있다.package-lock.json
에 반영되므로, Git에 포함하여 버전 관리하는 것이 일반적이다.package.json
은 의존성을 선언하는 역할을 하고, package-lock.json
은 실제 설치된 패키지의 버전을 고정하여 환경을 일관되게 유지하는 역할을 합니다.package-lock.json
을 Git에 포함하고, npm ci
를 사용하여 동일한 환경을 재현하는 것이 좋다.npm install
vs npm ci
npm install
과 npm ci
의 실행 방식을 비교한 다이어그램
sequenceDiagram
participant User
participant npm
participant packageJSON as package.json
participant packageLock as package-lock.json
participant nodeModules as node_modules
participant Registry
User->>npm: 실행 "npm install"
npm->>packageJSON: 의존성 확인
npm->>packageLock: 버전 확인
npm->>nodeModules: 설치할 패키지 결정
npm->>Registry: 최신 또는 범위 내 버전 다운로드
npm->>nodeModules: 패키지 설치
npm->>packageLock: 변경 사항 반영 (업데이트)
Note right of npm: package-lock.json 업데이트 가능
User->>npm: 실행 "npm ci"
npm->>packageLock: 의존성 버전 확인
npm->>nodeModules: 기존 폴더 삭제
npm->>Registry: 정확한 버전의 패키지 다운로드
npm->>nodeModules: 패키지 설치
Note right of npm: package-lock.json이 없으면 실패
npm install
npm install
은 package.json
과 package-lock.json
을 기반으로 의존성을 설치하며, 필요 시 package-lock.json
을 업데이트한다.node_modules
폴더가 존재하면 기존 파일을 유지하면서 변경된 패키지만 설치한다.package.json
에서 지정한 범위 내에서 유동적으로 변경될 수 있다.npm ci
npm ci
는 package-lock.json
에 명시된 정확한 버전을 설치하며, package.json
을 단순히 검증 용도로만 사용한다.node_modules
폴더를 삭제한 후 재설치하기 때문에, 항상 일관된 환경을 유지할 수 있다.package-lock.json
이 없으면 오류가 발생하며, package-lock.json
과 package.json
간의 버전 불일치가 있으면 실행이 실패한다.결론은 npm ci
가 CI/CD에 적합합니다. CI/CD 환경에서는 재현 가능한 빌드(reproducible builds)가 가장 중요하다고 생각합니다. CI/CD라는 것 자체가 빠른 배포 주기를 달성하기 위함이고, 이 배포 주기의 단축에는 서비스의 신뢰성이 동반되어야 합니다. 그 신뢰성을 위해서는 언제 어디서나 빌드하더라도 정상 동작한다는 보장이 있어야 하고, 그게 바로 재현 가능한 빌드입니다. 그 재현 가능한 빌드를 위해서는 최대한 해당 소프트웨어를 구동하는 데 필요한 라이브러리 레벨에 대해 변경을 최소화해야 하며 변경할 경우 충분한 테스트가 선행되어야 합니다.
따라서npm ci
는 정확한 버전을 설치하며, node_modules
을 초기화한 후 패키지를 다시 설치하기 때문에 일관성을 유지하고, 예기치 않은 패키지 변경을 방지할 수 있기 때문에 CI/CD에 적합합니다.
일관된 빌드 환경 유지
npm ci
는 package-lock.json
에 정의된 정확한 버전의 패키지를 설치하기 때문에, 개발 환경과 CI/CD 환경 간의 의존성 차이를 방지할 수 있다.npm install
은 package.json
의 버전 범위(^
, ~
)에 따라 다르게 동작할 수 있어, 예상치 못한 의존성 변경이 발생할 가능성이 있다.설치 속도
npm ci
는 기존 node_modules
을 삭제하고 한 번에 모든 패키지를 설치한다.npm install
은 이미 존재하는 패키지를 검토하고, 변경된 패키지만 업데이트한다.npm ci
를 CI/CD에서 사용할 경우, node_modules
를 캐시하지 않는 편이 더 좋지 않을까 생각한다.
패키지 변경 없이 재현 가능
npm ci
는 package-lock.json
을 엄격하게 따르므로, 동일한 패키지 버전이 유지됨.쓰기 권한이 필요 없음
npm ci
는 package-lock.json
을 변경하지 않으며, 항상 동일한 환경을 재현하기 때문에 빌드 안정성을 보장함.