설치된 라이브러리가 많은 프로젝트의 npm registry 변경하기 with package-lock.json 이해

최근 회사에서 N년 이상 성숙된 프로젝트의 npm registry를 사내 registry로 변경하는 업무를 진행했다.
처음에는 정석대로 프로젝트내 npm registry를 변경하고 npm i로 package-lock.json 을 재생성했다. 버전 표기에 의해 각 라이브러리들은 버전이 변경 될 수 있음을 알았으나 의존성 변경으로 인해 코드 수정이 필요할 수 밖에 없었다. 코드야 수정하면 되지만 이로 인한 regression test도 필요하고 부수효과가 어떻게 생길지 모르기때문에 큰 어려움이 생겼다. 그렇다고 라이브러리를 equal 버전으로 만들고 설치하는 것도 큰 공수였다.

그래서 이번 글은 npm registry 변경하는 과정과 트러블슈팅 해결과정을 공유하는 내용이다.

TL;DR

  1. npm registry 변경
  2. node_moudles 및 package-lock.json 삭제
  3. npm i 로 의존성 설치
  4. caret/tilde 등 버전 표기에 의해 설치된 버전이 기존과 달라져 오류가 발생한다면
  5. rollback 후 package-lock.json의 resolved url만 변경하고자 하는 npm registry url로 변경한다.

npm registry 변경하기

NPM의 기본 레지스트리는 https://registry.npmjs.org/이다. 그러나 레지스트리를 변경해야 하는 경우 NPM 레지스트리를 변경하는 방법에 대해 자세히 알아보고, 예제 코드와 결과를 통해 각 방법을 비교한다.

npm 레지스트리 변경은 크게 세 가지 방법이 있다.

  1. .npmrc 파일 설정
  2. 커맨드 라인을 통한 설정
  3. package.json 내 설정

방법 1: .npmrc 파일 사용하기

.npmrc 파일은 NPM 설정을 저장하는 파일이다. 이 파일을 사용하여 NPM 레지스트리를 변경할 수 있다.

  1. 프로젝트의 루트 디렉토리에 .npmrc 파일을 생성한다.
  2. 생성한 파일에 registry=<레지스트리 주소>를 추가한다.
echo "registry=https://my-custom-registry.com/" > .npmrc  

그럼 .npmrc 파일이 생성되고, 해당 파일 안에는 레지스트리 주소가 저장된다.

방법 2: CLI 명령어 사용하기

CLI (Command Line Interface)를 통해 NPM 레지스트리를 변경할 수 있다.
터미널에서 npm config set registry <레지스트리 주소>를 실행한다.

npm config set registry https://my-custom-registry.com/  

CLI를 통해 전역 NPM 설정이 변경된다. ~/.npmrc에 레지스트리 주소가 저장된다.

방법 3: package.json 파일 사용하기 (publish)

package.json 파일을 통해 NPM 레지스트리를 변경할 수 있다.

  1. package.json 파일에 publishConfig 항목을 추가한다.
  2. publishConfig에 registry 항목을 추가하고 원하는 레지스트리 주소를 설정한다.
{
  "name": "my-package",
  "version": "1.0.0",
  "publishConfig": {
    "registry": "https://my-custom-registry.com/"
  }
}

해당 프로젝트에서 npm publish 명령을 사용할 때, 지정한 레지스트리 주소를 사용한다.

.npmrc vs CLI vs pakcage.json

.npmrc 파일CLI 명령어pakcage.json 파일
범위프로젝트전역프로젝트
우선 순위높음중간낮음
특징프로젝트별 설정 가능전역 설정, 쉬운 방법`npm publish` 명령어 실행시 설정 적용
사용 경우특정 프로젝트에만 적용이 필요할 때모든 프로젝트에서 동일한 레지스트리를 사용할 때패키지를 출판할 때 특정 레지스트리를 사용하려 할 때

package-lock.json 이해하기

package-lock.json은 Node.js 프로젝트에서 사용되는 npm(Node Package Manager)이 생성하는 파일로 npm install 명령을 실행하면 package-lock.json 파일이 생성된다.
프로젝트의 종속성을 추적하고, 동일한 설치 과정을 보장하기 위한 것이다. package-lock.json 파일에는 각 패키지의 정확한 버전, 다운로드 URL, 체크섬 등이 기록되어 있다.

  1. 정확한 의존성 관리: package-lock.json 파일은 패키지가 설치된 정확한 버전을 포함하므로, 다른 개발자가 프로젝트를 복제하거나 패키지를 다시 설치할 때 항상 동일한 의존성 트리를 얻을 수 있다.
  2. 빌드의 일관성: package-lock.json 파일은 패키지가 설치된 경로와 파일 구조를 포함하므로, 다른 개발자나 다른 환경에서 프로젝트를 빌드할 때 일관된 결과를 얻을 수 있다.
  3. 보안과 신뢰성: package-lock.json 파일은 패키지의 해시 값(integrity)을 포함하여, 설치된 패키지가 변경되지 않았는지 확인할 수 있다. 이는 패키지의 무단 변경이나 조작을 탐지하는 데 도움을 준다.

즉, package-lock.json은 npm을 통해 프로젝트에 설치된 패키지의 정확한 버전 및 의존성 관리를 제공하여 프로젝트의 일관성과 신뢰성을 유지하는 데 중요한 역할을 한다.

package.json내 버전 표기 방식

이런 package-lock.json에 명시되는 버전은 package.json에 의해 결정된다.
package.json에는 라이브러리의 버전 명시를 상황에 맞게 기호를 통해 다양하게 할 수 있다. 즉, 종속성의 업데이트 수준을 세밀하게 조정할 수 있다.

기호의미
없음정확한 버전. 예: 1.2.3
tilde(~)PATCH-level changes 허용. 예: ~1.2.3
caret(^)MINOR-level changes까지 허용. 예: ^1.2.3
asterisk(*)어떤 버전도 허용. 예: *
greater than(>)특정 버전보다 높아야 함. 예: >1.2.3
less than(<)특정 버전보다 낮아야 함. 예: <1.2.3
equals(=)정확한 버전. 예: =1.2.3
hyphen(-)범위 지정. 예: 1.2.3 - 2.3.4
x or X or *버전 대체. 예: 1.2.x

package-lock.json 재생성하기

앞서 변경한 npm registry를 사용하여 라이브러리 의존성을 업데이트 해줘야 변경 작업이 완료된다.

  1. 프로젝트내 node_modules 폴더를 삭제하고
  2. package-lock.json 파일을 삭제하고
  3. ‘npm install’ 명령어로 설치를 진행한다.
  4. 설치 중 오류가 발생하여 해결했다면 ‘npm cache clean —force’로 npm 캐시 초기화하여 다시 install을 진행한다.

그럼 package-lock.json 변경된 내용으로 생성되고, 프로젝트가 정상 작동하는지 테스트를 거쳐 작업을 완료한다.

하지만, 여기서 끝나지 않는다.

행복하게도 오류가 없이 끝나면 좋겠지만, 역시나 오류가 발생한다.
라이브러리 대부분의 버전이 caret/tilde이다 보니 설치된 버전이 동시 다발로 변경되면서 호환이 되지 않거나 코드 업데이트가 필요한 경우도 많이 생겼다. 코드야 수정하면 되지만 이 수정에 따른 regression test가 필요하고, 프로젝트 규모상 이로 인한 부수효과가 어떤 것이 생길지 파악하기 어렵고 파악하는데 예측 불가한 시간이 소요된다.

그래서 이제부터 중요하다!

resolved URL replace 하기

변경하려고 했던 사내 npm registry는 기본 https://registry.npmjs.org/ 를 미러링하고 있기 때문에, 라이브러리 버전이 같다면 당연히 해시 값(integrity)은 동일하다. 그래서 package-lock.json을 재성성하지 않고 resolved만 Find/Replace로 변경하는 것이다.

resolved 변경 전(https://registry.npmjs.org) @babel/parser의 버전 정보

"node_modules/@babel/parser": {
  "version": "7.21.2",
  "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.2.tgz",
  "integrity": "sha512-URpaIJQwEkEC2T9Kn+Ai6Xe/02iNaVCuT/PtoRz3GPVJVDpPd7mLo+VddTbhCRU9TXqW5mSrQfXZyi8kDKOVpQ==",
  "bin": {
    "parser": "bin/babel-parser.js"
  },
  "engines": {
    "node": ">=6.0.0"
  }
},

resolved 변경 후(https://my-custom-registry.com) @babel/parser의 버전 정보

"node_modules/@babel/parser": {
  "version": "7.21.2",
  "resolved": "https://my-custom-registry.com/@babel/parser/-/parser-7.21.2.tgz",
  "integrity": "sha512-URpaIJQwEkEC2T9Kn+Ai6Xe/02iNaVCuT/PtoRz3GPVJVDpPd7mLo+VddTbhCRU9TXqW5mSrQfXZyi8kDKOVpQ==",
  "bin": {
    "parser": "bin/babel-parser.js"
  },
  "engines": {
    "node": ">=6.0.0"
  }
},

단, resolved URL을 변경한 후 integrity 체크섬이 유효한지 확인해야 한다. URL이 미러링하는 패키지 내용이 원본과 동일하다면 체크섬 검증에 문제가 없지만, 그렇지 않다면 npm 설치 과정에서 오류가 발생한다.

integrity 체크섬의 검증은 패키지 설치 과정에서 자동으로 이루어진다. 패키지를 다운로드 받은 후, 그 내용에 대한 체크섬을 계산하고 package-lock.json에 기록된 체크섬과 비교한다. 이 두 체크섬이 일치하지 않으면 npm은 패키지 설치를 중단하고 오류 메시지를 출력한다. 이렇게 함으로써 패키지 내용이 예상치 않게 변경되는 것을 방지하고, 원본 패키지와 동일한 패키지를 사용하고 있다는 것을 보장한다.

따라서, resolved URL을 변경하고 npm install을 실행하면 자동으로 체크섬의 유효성을 검사하게 된다. 오류가 발생하지 않고 모든 패키지가 정상적으로 설치되면, 변경된 URL과 체크섬이 유효하다는 것을 의미한다.

결론

npm 레지스트리를 변경하는 것은 신중해야 하는 작업이다. 사용자의 보안 및 프로젝트 종속성 관리에 직접적인 영향을 미친다. 따라서 변경 전 후에는 반드시 레지스트리 주소가 올바른지, 변경된 레지스트리에서 패키지를 제대로 가져올 수 있는지 확인해야 한다.

npm 레지스트리 변경은 종종 필요한 작업이며, 다양한 방법으로 수행할 수 있다. 변경 방법을 선택할 때는 프로젝트의 요구사항, 개발 환경, 보안 요구사항 등을 고려해야 한다. 변경 후에는 반드시 적용이 잘 되었는지, 그리고 모든 종속성이 제대로 설치되는지 확인해야 한다.



쿠팡 파트너스 활동을 통해 일정액의 커미션을 제공받을 수 있습니다.