Node.js 프로젝트에서 package.json의 의존성 버전을 관리할 때 자주 보이는 기호가 있습니다. 바로 틸트(~)와 캐럿(^)인데요, 이들은 패키지 버전을 자동으로 업데이트할 수 있는 범위를 지정하는 역할을 합니다. 또한 이 규칙은 SemVer(Semantic Versioning, 유의적 버전)이라는 버전 관리 체계 위에서 동작합니다.
SemVer 기본 구조
SemVer은 다음과 같이 메이저.마이너.패치 3단계로 나눕니다.
MAJOR.MINOR.PATCH
- 메이저(MAJOR): 하위 호환성이 깨질 수 있는 변경 (예:
1.x.x → 2.0.0) - 마이너(MINOR): 새로운 기능 추가, 하위 호환 유지 (예:
1.2.x → 1.3.0) - 패치(PATCH): 버그 수정, 하위 호환 유지 (예:
1.2.3 → 1.2.4)
Package.json 의존성 버전 관리
1. 틸트(~) 연산자
- 형식:
~1.2.3 - 허용 범위: 패치 버전 업데이트만 허용
- 의미:
>=1.2.3 <1.3.0
예시:
~1.2.3→1.2.3,1.2.4,1.2.9가능1.3.0이상은 불가능
보수적으로 버그 수정 업데이트만 반영하고 싶을 때 적합합니다.
2. 캐럿(^) 연산자
- 형식:
^1.2.3 - 허용 범위: 마이너 + 패치 버전 업데이트 허용
- 의미:
>=1.2.3 <2.0.0
예시:
^1.2.3→1.2.3,1.3.0,1.9.9가능2.0.0이상은 불가능
기능 확장을 포함한 업데이트를 적극 반영하고 싶을 때 적합합니다.
3. 비교 정리
| 표기 | 허용 범위 | 주 용도 |
|---|---|---|
~1.2.3 |
>=1.2.3 <1.3.0 |
패치 업데이트만 허용 (보수적) |
^1.2.3 |
>=1.2.3 <2.0.0 |
마이너 + 패치 업데이트 허용 (적극적) |
4. 메이저 버전은 자동으로 올릴 수 없습니다.
여기서 중요한 점은, 메이저 버전은 자동으로 올려주는 기능이 기본적으로 없다는 것입니다.
- 이유: 메이저 버전은 하위 호환성을 깨뜨릴 수 있어 프로젝트가 깨질 위험이 큼
- 따라서 npm은 의도적으로 메이저 자동 업데이트를 지원하지 않음
메이저 업데이트 방법
- 수동 반영:
npm install some-package@latest- 도구 활용 (
npm-check-updates): npx npm-check-updates -u npm install
5. 실제 예시 — React
{
"dependencies": {
"react": "^18.2.0",
"react-dom": "~18.2.0"
}
}
react:^18.2.0→18.2.x,18.3.x,18.9.x까지 자동 반영react-dom:~18.2.0→18.2.x까지만 자동 반영 (패치만 허용)
정리
~: 패치만 자동 업데이트 (보수적)^: 마이너+패치 자동 업데이트 (적극적)- 메이저 버전은 직접 확인 후 반영해야 안전
즉, package.json의 틸트(~)와 캐럿(^)는 SemVer 규칙에 맞춰 업데이트 가능 범위를 사전에 제한하는 것이라고 볼 수 있습니다.