npm install과 npm ci의 차이 - TEAM-ARK/inflearn-clone-front GitHub Wiki

들어가기 전에

최근에 git clone 후 npm install을 했을 때 package-lock.json가 변경되는 문제를 겪었고 npm ci 명령어를 통해 해결하게 되었던 일이 있었다.

이 문제를 통해 package-lock.json이 존재한다고 하더라고 npm 버전에 따라 npm install이 다르게 구동되어 package-lock.json을 기존과 다른 내용으로 덮어쓸 수 있게 된다는 것을 알게 되었다.

그럼 npm ci는 무엇이기에 이런 문제를 해결해 준 걸까?
그리고 모듈을 설치할 때 무조건 npm ci를 사용하면 되는 걸까?

위의 궁금증 해결을 위해 npm install과 npm ci가 무엇이고, 둘의 차이는 어떤 것인지 그리고 언제 사용하면 좋을지에 대해 정리를 해봤다.

npm install

소개

먼저 npm install은 패키지와 패키지가 의존하는 모듈을 설치하는 명령어이며, npm i 혹은 npm add로 쓰기도 한다.

사용 방법

npm install는 다음과 같이 명령어를 이용할 수 있다.

  • 개별적으로 패키지를 설치할 때

    npm install 패키지_이름
    

    위와 같은 방법으로 사용하면 package.json과 package-lock.json이 없는 경우에는 이 2개의 파일이 생성되고, package.json과 package-lock.json이 존재한다면 dependencies에 패키지가 추가된다.

  • pacakge.json의 dependencies에 나열되어 있는 패키지를 설치할 때

    npm install
    

    이때 package.json의 요구 사항(dependencies)을 만족해야 package-lock.json을 적용된다. 만약 요구 사항을 만족하지 않는다면 pacakge를 업데이트하고 package-lock.json 파일의 내용이 변경된다.

이 외에도 npm install 사용 방법은 다양하다. 이 글에서는 npm install과 npm ci 차이 설명이 주목적이기 때문에 가볍게 정리하고 넘어가지만 더 자세히 알고 싶다면 여기(npm-install 공식 문서)를 참고하면 된다.

npm ci

소개

npm ci는 npm install 과 유사하지만, npm install과 달리 같은 개발 환경을 구축해 줄 수 있기 때문에 테스트 플랫폼, 지속적인 통합 및 배포(CI와 CD)와 같은 자동화된 환경이나 dependencies를 새로 설치해야 하는 모든 상황에서 사용할 수 있는 명령어이다.

참고로 5.7.0 버전부터 지원한 명령어이며, npm 공식 블로그에 따르면, 이름에서 알 수 있듯이 CI(Continuous Integration) 환경에 큰 이점이 될 것이라고 생각하고 있다.​

사용 방법

사용 방법은 단순히 npm ci 명령어를 입력만 해주면 된다.

npm ci

주의 사항

  1. npm ci는 pacakge-lock.json 기반으로 설치가 진행되기 때문에 package-lock.json이나 npm-shrinkwrap.json 파일이 꼭 존재해야 한다.
    만약 package-lock.json이 없다면 아래와 같은 결과를 출력하고 패키지 설치가 진행되지 않는다.

    added 1 packages in 4.892s
    
  2. npm ci는 아래와 같이 사용할 수 없다.

    npm ci 패키지_이름
    

    npm ci는 한 번에 전체 프로젝트만 설치할 수 있기 때문에 개별적으로 패키지를 설치하는 것이 불가능하다.

  3. 이미 node_modules 폴더가 존재하는 경우에 npm ci를 실행시키면 기존 node_modules 폴더를 삭제하고 다시 설치한다.

  4. package-lock.json의 dependencies가 package.json의 dependecies와 일치하지 않는다면, npm ci는 package-lock.json을 업데이트 하는 대신에 오류와 함께 종료한다.

npm install 과 npm ci의 속도 비교

  • npm install로 설치했을 때
    added 1032 packages from 651 contributors and audited 1039 packages in 236.795s
    
  • npm ci로 설치했을 때
    added 1033 packages in 135.108s
    

npm install을 사용해서 1032개의 패키지를 설치했을 때 236.795초가 걸렸고, npm ci를 사용해서 1033개의 패키지를 설치했을 때 135.108초가 걸렸다.

위의 결과를 통해 npm ci가 npm install 보다 더 빠르다는 것을 알 수 있다.

npm ci가 npm install 보다 빠른 이유는 지정된 버전의 패키지만 설치하면 돼서 최신 호환 버전을 확인하는 과정이 필요 없기 때문이다.

참고로, npm ci는 다음과 같은 경우에 훨씬 더 빠를 것이다.

  • package-lock.json 혹은 npm-shrinkwrap.json 파일이 있을 때

  • node_modules 폴더가 없거나 비었을 때

참고 - npm-shrinkwrap.json 이란? dependencies에 설치된 패키지의 버전을 고정시키는 명령어인 npm shrinkwrap를 실행시켰을 때 생성되는 파일로서, 패키지가 의존하고 있는 모듈의 버전과 정보를 갖고 있다.

npm install 과 npm ci의 차이점

아래의 표는 Diffrence between npm i and npm ci in Node.js 내용을 발췌하여 해석한 것이다. 참고로 일부 해석 중 의역한 것이 있으니 감안하고 보시길 바란다.

No npm install npm ci
1. 개별적으로 패키지를 설치할 수 있고, dependencies에 있는 모듈을 설치한다. 개별적으로 패키지를 설치할 수 없고, 일반적으로 dependencies에 있는 모듈을 설치하는 데 사용함.
2. 명령어를 실행했을 때, package.json이나 package-lock.json에 작성할 수 있음. 명령어를 실행했을 때, package.json이나 package-lock.json에 절대 작성할 수 없음.
3. 개별 dependencies를 추가할 수 있음. 개별 dependencies를 추가할 수 없음.
4. 실행 속도가 느림. 실행 속도가 빠름.
5. 어떤 dependency가 package-lock.json에 없다면, 이 명령어로 dependency를 추가함. 어떤 dependency가 없거나 호환되지 않는 버전이 있다면, npm ci에서 오류가 발생함.
6. 만약 node_modules가 이미 존재한다면, 이 명령어는 node_modules를 변경하지 않음. 만약 node_modules가 이미 존재한다면, npm ci가 설치를 시작하기 전에 자동으로 node_modules를 제거함.
7. global 패키지로 설치 가능함. global 패키지로 설치 불가능함.
8. npm i pacakge-name은 dependencies를 추가하거나 업데이트하는 package.json에 대한 권한에 사용됨. package.json에 작성하는 데 사용할 수 없음.
9. npm i는 일부 dependencies의 버전을 고정하기 위해 package-lock.json을 바로잡을 수 있음. package-lock.json을 작성할 수 없음.
10. dependencies의 목록을 업데이트하는 변경 사항을 가져온 후 개발하는 동안 사용됨. 항상 고정된 결과를 가져오거나(deteministic), 반복 가능한 빌드에 사용됨.

언제 npm install과 npm ci를 사용하면 좋을까?

※주의: 아래의 상황이 꼭 정답은 아니며, 아래에 적은 상황보다 더 다양한 상황들이 존재할 것이다. 참고만 해주시길 바란다.

npm ci를 추천하는 상황

npm ci는 다음과 같은 상황에서 사용하는 것을 추천한다.

  1. 협업을 하고 있거나 같은 개발 환경을 구축해야하는 상황 ​

    npm install은 package-lock.json이 없을 경우 package.json의 dependencies에 나열된 패키지를 설치하는데 이때, 패키지의 버전이 고정된 것이 아니라 ^나 ~로 인해 범위로 표현되어 처음에 패키지를 설치할 때의 버전과 동일한 버전을 설치하지 않게 되는 문제가 생길 수 있다.

    예를 들어서 package.json의 depencency에 다음과 같이 버전이 표기되어 있다고 가정해 본다.

    "dependencies": {
      "express": "^4.0.0"
    }
    

    그리고 express에서 작은 버그 수정 등으로 인해 버전이 4.0.1로 업데이트가 된 후 npm install를 실행시키면, 4.0.0이 아닌 4.0.1이 설치될 수 있다. ​

    참고 - ^와 ~ 의미

    • ^(Caret, 캐럿) : 하위 호환성이 보장되어 지정한 버전의 두 번째 자리까지의 범위 내에서 모두 업데이트
      ex. ^4.0.2로 되어있다면 4.0.2 <= 업데이트될 버전 < 5.0.0으로 업데이트할 범위가 지정된다.
    • ~(Tilde, 틸드) : 현재 지정한 버전의 마지막 자리 범위 내에서만 업데이트
      ex. ~4.0.2로 되어있다면 4.0.2 <= 업데이트될 버전 < 4.1.0으로 업데이트할 범위가 지정된다.

    또한 package-lock.json이 존재한다고 하더라도 npm 버전에 따라 npm install 구동 방식이 달라서 package-lock.json 이 변경되기도 한다.
    하지만 npm ci는 npm 버전이 다르더라도 같은 개발 환경을 구축해준다.

  2. 보안을 고려하는 상황 npm ci는 매번 같은 버전으로 설치하기 때문에 악성코드를 설치할 가능성이 줄어들어 보안성에 좋다.

npm install을 추천하는 상황

그럼 npm install은 언제 사용해야 할까?

위에서 설명했듯이 npm ci는 개별적으로 패키지를 설치하는 것이 불가능하다.

따라서 아래와 같은 상황이라면 npm install을 사용하면 된다.

  1. 개별적으로 패키지를 추가하려고 할 때
  2. 패키지의 새로운 기능과 성능 개선, 버그 수정 등으로 업데이트가 필요할 때

마무리하며

npm install과 npm ci는 조금 다른 목적으로 존재한다.
npm install은 개별 패키지 및 dependencies에서 가능한 최신 버전을 설치해 주고, npm ci는 처음 패키지를 설치했을 때와 동일한 버전을 설치하게 해준다.

그렇기에 자신의 개발 환경에 맞는 명령어를 사용하면 될 것 같다.

여담으로 모르고 보면 둘이 유사해 보이고 npm ci가 더 나아 보여서 npm ci만 사용하면 되는 거 아닌가 싶은 생각이 처음에 들었지만, 이렇게 꼼꼼히 따져보니 공통된 기능을 하는 명령어가 아니고 개발 상황에 따라 사용되는 명령어가 다르기에 어느 것이 옳고 그르다, 더 낫고 별로다 라고 할 수 없는 것 같다는 생각을 하게 되었다.

참고

npm install과 npm ci의 차이
npm install 시 package-lock.json이 변경되는 이유
npm install을 사용하지 말아야 할 때
npm install과 npm ci의 차이 설명 및 package-lock.json이 존재하는 이유와 어떻게 동작하는가

npm install
npm install 공식 문서
npm install 동작에 대한 설명

npm ci
npm ci 공식 문서
npm 5.7.0v 공개 당시 npm ci를 소개한 npm 공식 블로그
npm ci 실행 시 npm audit이 함께 실행되는지에 대한 글

package.json
package.json 공식 문서
^(캐럿)과 ~(틸드)에 관한 설명

package-lock.json
package-lock.json 이란

npm-shrinkwrap
npm shrinkwrap 공식 문서
npm-shrinkwrap에 관한 설명

개인 블로그 원본

https://blog.naver.com/dudu1104/222509189411