가끔씩 패키지 업데이트를 하는 경우 종종 문제가 있어서 정리차원에서 남긴다.
Breaking Change
브레이킹 체인지는 패키지나 모듈을 업데이트했을 때 기존 코드가 더 이상 정상 동작하지 않게 되는 변경사항을 의미한다.
예를 들어 패키지 A가 v1에서 v2로 업데이트되면서 다음과 같은 변경사항이 생겼다고 해보자.
- 함수 이름이 변경됨
- 함수의 매개변수가 달라짐
- 기존에 있던 기능이 deprecated되거나 사라짐
- 반환값의 형태가 변경됨
- 기존 사용 방식이 더 이상 지원되지 않음
프로젝트 코드가 v1 기준으로 작성되어 있었다면, v2로 업데이트했을 때 기존 코드가 깨질 수 있다. Semantic Versioning(SemVer) 기준으로는 버전을 MAJOR.MINOR.PATCH 형태로 표현한다. 이 중 기존 버전과 호환되지 않는 변경사항이 있을 때 MAJOR 버전을 올린다.
예를 들어 아래처럼 1.x.x에서 2.0.0으로 올라간다면 breaking change가 포함되어 있을 가능성이 있다.
1.x.x → 2.0.0
다만 모든 패키지가 SemVer를 완벽하게 지키는 것은 아니기 때문에, 실제 업데이트 전에는 changelog나 migration guide를 확인하는 것이 좋다.
Peer Dependency
Peer Dependency는 간단히 말하면 “이 패키지는 특정 의존성이 필요하지만, 그 의존성을 직접 설치해서 포함하지는 않으니 프로젝트 쪽에서 설치해줘”라는 의미다. 예를 들어 어떤 React 컴포넌트 라이브러리의 package.json에 아래처럼 적혀 있다고 하자.
{
"peerDependencies": {
"react": "^18.0.0"
}
}
위 React 컴포넌트 라이브러리는 react가 필요하지만, 패키지 자체적으로 React를 번들하거나 별도로 포함하지 않는다. 대신 이 라이브러리를 사용하는 프로젝트에 이미 설치된 React를 함께 사용하겠다는 의미다. 왜냐하면 React 같은 라이브러리는 프로젝트 전체에서 같은 인스턴스를 공유해야 하는 경우가 많기 때문이다.
| 문제 | 설명 |
|---|---|
| 중복 방지 | 라이브러리 A도 React를 설치하고, 프로젝트도 React를 설치하면 React가 여러 개 존재할 수 있다. |
| 충돌 방지 | React 같은 라이브러리는 인스턴스가 여러 개일 때 런타임 문제가 발생할 수 있다. |
| 버전 호환 | 라이브러리가 요구하는 버전과 프로젝트의 버전이 맞는지 패키지 매니저가 확인할 수 있다. |
Breaking Change와 Peer Dependency의 관계
Breaking Change와 Peer Dependency는 서로 다른 개념이지만, 실무에서는 자주 같이 엮인다. 예를 들어 next-intl이 peer dependency로 next: ^14.0.0을 요구한다고 하자. 그런데 프로젝트에서 Next.js를 15로 올리면 next-intl 입장에서는 자신이 기대하는 Next.js 버전 범위를 벗어나게 된다.
프로젝트
→ next@15 사용
next-intl
→ next@^14.0.0 기대
이 경우 peer dependency 버전 범위에 맞지 않아 경고가 발생하거나, 환경에 따라 설치가 실패할 수 있다. 그리고 Next.js 15에서 next-intl이 의존하던 동작이 바뀌었거나 제거되었다면 breaking change의 영향을 받을 수도 있다. 그런데 패키지 간 의존성 문제로 peer dependency 경고가 발생하더라도, 실무에서는 상황을 감안하고 그대로 사용하는 경우도 있다. 예를 들어 React 19가 나왔지만 어떤 패키지는 peer dependency에 React 18까지만 명시하고 있을 수 있다. 이때 peer dependency에 명시된 버전 범위는 “이 범위 밖에서는 물리적으로 절대 동작하지 않는다”는 의미라기보다는 “이 범위 안에서 동작을 기대하거나 테스트했다”는 의미에 가깝다.
그래서 프로젝트 루트에 React 19가 있고, 어떤 패키지가 React 18까지만 peer dependency로 명시하고 있더라도 실제 런타임에서는 정상 동작할 수 있다. 다만 패키지 매니저 설정에 따라 경고만 나오고 설치될 수도 있고, 설치 단계에서 실패할 수도 있다.
React 19 릴리스
↓
Next.js가 React 19 지원 추가
↓
인기 라이브러리들이 React 19 지원 추가
↓
중소 라이브러리들이 React 19 지원 추가
↓
유지보수가 멈춘 라이브러리는 계속 미지원 상태로 남을 수 있음
실무에서는 peer dependency 경고가 나와도 실제로 동작하면 경고를 감수하고 사용하기도 한다. 이러한 경고는 보통 “상위 버전 환경에서 테스트되었거나 보장된 범위를 벗어났다”는 의미이지, 반드시 동작하지 않는다는 의미는 아니다. 반대로 타입 에러나 런타임 문제가 발생한다면 임시로 우회하거나, 근본적으로는 대체 라이브러리로 교체해야 할 수도 있다. 이조차 애매하다면 다른 패키지들이 React 19 같은 새 버전을 충분히 따라올 때까지 업그레이드 시점을 늦추기도 한다. 모든 패키지의 peer dependency가 항상 완벽하게 맞물리지는 않기 때문이다.
결국 브레이킹 체인지는 패키지를 업데이트했을 때 기존 코드가 깨질 수 있는 변경사항을 의미한다. Peer Dependency는 필요한 의존성 패키지를 패키지 자체에서 직접 가지고 있는 것이 아니라, 해당 패키지를 사용하는 프로젝트에 설치하도록 요구하고 함께 사용하려는 목적의 의존성이다.