자바스크립트 패키지 매니저
패키지를 프로젝트에 설치, 갱신, 삭제하는데 사용되는 도구를 패키지 매니저라고 한다. 자바스크립트의 패키지 매니저는 npm, yarn이 있다.
두가지 모두 패키지 잠금 기능을 지원한다. npm은 package-lock.json을, yarn은 yarn.lock 파일을 패키지 잠금 파일로 사용한다. 즉, 패키지 잠금 파일은 프로젝트에서 어떤 패키지 매니저를 사용하는지에 따라 달라진다.
패키지 관리 매커니즘
npm을 사용하든 yarn을 사용하든 프로젝트의 메타 정보는 package.json을 통해 관리된다. package.json에는 해당 프로젝트가 의존하고 있는 모든 패키지 이름과 버전이 나열되어 있다. 일반적으로 설치되어야 하는 패키지들은 dependencies에, 개발할 때만 필요한 패키지들은 devDependencies 항목에 명시된다.
설치가 필요한 패키지들이 package.json에 등록되어 있으면 프로젝트의 모든 개발자들은 패키지 매니저의 설치 커맨드 하나만으로 모든 패키지를 한번에 설치할 수 있다. 아래와 같이 프로젝트에서 사용하고 있는 패키지 매니저에 따라 설치 커맨드를 입력하면 package.json에 등록되어 있는 모든 패키지들이 npm registry로부터 다운받아져 node_modules 디렉터리에 저장된다.
npm
$npm i
또는
$npm install
yarn
$yarn
또는
$yarn install
패키지 버전
그렇다면 같은 package.json 파일만 있으면 모두 동일한 버전의 패키지를 설치할 수 있지 않을까? → 그렇지 않다.
왜냐하면 package.json에 명시한 패키지의 버전들이 ~(틸드, tilde)와 ^(캐럿, caret)로 인해 버전의 범위가 달라지기 때문이다.
Semantic Versioning(semver)
Semantic Versioning은 버전 명의 작성 방식에 관한 기준이 패키지마다 다른 문제를 해결하기 위해 만든 제안이다.
X.Y.Z 버전 형태로 나타내고 X는 Major 버전, Y는 Minor 버전, Z는 Patch 버전이다. Major는 하위호환이 되지 않는 API 변화들, Minor는 하위호환이 되는 범위 내에서 기능 추가들, Patch는 하위호환이 되는 범위 내에서 bug fix를 의미한다.
틸드(tilde), 캐럿(caret)
- 틸드(~): X.Y.Z 중 Z 범위 내에서 버전 업데이트
- 캐럿(^): X.Y.Z 중 X 이하 하위호환성이 보장되는 범위 내에서 버전 업데이트
- ~1.2.3: >=1.2.3, <1.3.0
- 이 경우 범위가 1.2.3과 같거나 크고, 1.3.0보다 작은 범위 내에서 업데이트한다.
- ^1.2.3: >=1.2.3, <2.0.0
- 1.2.3보다 크거나 같고, 2.0.0보다 작은 범위 내에서 업데이트한다. 결국 Major 버전이 바뀌지 않고, 하위호환성을 유지하기 때문에 가장 많이 사용한다.
패키지 잠금 파일이 필요한 이유
설치 시점에 따라 달라지는 패키지 버전
예를들어 react 패키지가 ^16.8.2로 등록되어 있으면 SemVer 규칙에 따라 16.8.2이상~17.0.0 미만의 범위로 버전이 지정된다. 맨 처음 프로젝트를 세팅한 개발자 A가 특정 버전을 지정하지 않았다면 당시 react의 최신 버전은 16.8.2였을 것이다. 만약 추후 개발자 B가 패키지를 설치할 당시 react 패키지의 최신 버전이 16.9.1이었다면 B의 pc에는 16.9.1이 설치되어 있을 것이다. 게다가 프로젝트의 CI 서버가 배포할 때마다 매번 모든 패키지를 설치한다고 가정하면, 애플리케이션이 배포되는 서버에는 항상 그 당시 최신 버전의 react 패키지가 설치되어 사용될 것이다.
- package.json → ^16.8.2
- 개발자 A의 PC → 16.8.2
- 개발자 B의 PC → 16.9.1
- 개발/상용 서버 → 16.10.0
이렇게 서로 다른 버전의 패키지를 설치해서 사용하면 큰 혼선이 생길 수 있다(eg. A의 pc에서 성공하는 테스트가 다른 개발자의 PC에서는 실패하거나, 일부 특정 버그가 발생하는 등). 또한 실제 서버에 배포된 애플리케이션이 개발자 컴퓨터에서 돌아가는 애플리케이션과 100% 동일하게 작동한다는 보장이 없기 때문에 디버깅시 매우 난감할 수 있다.
패키지 잠금
이렇게 동일한 package.json을 사용해도 서로 다른 버전의 패키지가 설치되는 문제는 패키지 잠금을 통해 해결할 수 있다. package-lock.json이나 yarn.lock과 같은 패키지 잠금 파일에는 프로젝트에 최초로 추가될 당시에 정확히 어떤 버전이 설치되었는지가 기록된다.
이렇게 한번 lock 파일이 생성되면 그 이후로는 npm i(또는 yarn)를 실행했을 때 npm registry에 등록된 최신 버전을 설치하는 것이 아니라 항상 lock 파일에 명시되어 있는 버전으로 패키지를 설치해준다. 그렇기 때문에 설치 시점과 상관없이 항상 동일한 버전의 패키지가 설치되는 것을 보장받을 수 있다.
References
https://www.daleseo.com/js-package-locks/
https://umanking.github.io/2022/05/05/npm-version-tilde-caret/
https://umanking.github.io/2022/05/05/yarn-lock/
https://spoqa.github.io/2012/12/18/semantic-versioning.html
'TIL' 카테고리의 다른 글
[TIL] 23.03.08 TS 핸드북 - More on Functions (0) | 2023.03.09 |
---|---|
불필요한 node_modules 한번에 삭제하기 (0) | 2023.01.31 |
[TIL] 23.01.17 프리온보딩 챌린지 3회차 (0) | 2023.01.18 |
[TIL] 23.01.15 타입스크립트 핸드북 - More on Functions(2) (0) | 2023.01.16 |
[TIL] 23.01.11 타입스크립트 핸드북 - More on Functions(1) (0) | 2023.01.12 |