welcome to sisi's space! ‎ε(*⌒▽⌒)੭*゚¨゚゚・*:..☆

Dev & Study

[npm] peerDependency strictness란

Sisi_ 2026. 3. 3. 00:38

모노레포 환경에서 TypeScript 관련 이슈를 추적하다 보면, 단순히 버전이 맞는 것처럼 보이는데도 typecheck가 실패하는 상황을 겪을 수 있다. 이 문제의 원인이었던 것이 peerDependency strictness였다. 특히 Nx 기반 프로젝트에서 dependency tree가 invalid 상태로 판단되면 예상하지 못한 타입 충돌이 날 수 있다.

이 글은 peerDependencies가 무엇인지, npm이 이를 얼마나 엄격하게 처리하는지, 그리고 어떤 방식으로 문제를 해결했는지 다룬다.


peerDependencies란 무엇인가

peerDependencies는 이 패키지는 특정 라이브러리와 같은 인스턴스를 공유해서 사용해야 한다는 뜻이다.

예시:

{
  "peerDependencies": {
    "typescript": "^4.7.4"
  }
}

ㅇ 호환성 계약(compatibility contract)은 이 패키지는 TypeScript 4.7.x 계열에서 테스트되었고 그 범위를 벗어나면 정상 동작을 보장하지 않는다는 뜻이다.


npm의 peerDependency strictness

npm은 peerDependency 충돌을 어떻게 처리할지를 설정으로 관리한다.

peerDependency strictness: peerDependency 범위를 벗어나면 경고로 넘길 것인가, 아니면 invalid한 상태로 볼 것인가?

npm config set strict-peer-deps false

-> peerDependency 범위가 맞지 않아도 에러가 아니라 경고로 처리해라

 

dependency tree가 invalid로 표시되면 다음 문제가 발생할 수 있다.

  • Nx가 dependency graph를 잘못 인식
  • TypeScript 인스턴스가 여러 개로 분리
  • eslint / typecheck 실패
  • 프로젝트 그래프 충돌

반대로 invalid 플래그가 붙지 않으면

Nx / eslint / typecheck가 정상적인 단일 TypeScript 인스턴스로 인식하고 typecheck가 통과한다.


중요한 포인트: 이 설정은 미래의 설치에만 적용된다

strict-peer-deps 설정을 바꿨다고 해서 현재 node_modules 상태가 자동으로 수정되지는 않는다. 이유는 dependency tree의 상태가 다음 시점에 결정되기 때문이다.

  • peerDependency resolution
  • dedupe
  • hoisting

이 모든 계산은 설치 시점에 발생한다. 즉 다음 커맨드를 실행할 때다.

  • npm install
  • npm ci

이미 invalid 상태로 계산된 dependency tree는 설정을 바꿔도 자동으로 고쳐지지 않는다.


해결 방법

1. node_modules 제거

rm -rf node_modules

2. lockfile 기준으로 깨끗하게 설치하기

npm ci

3. Nx 캐시 초기화

npx nx reset

4. 필요하면 다시 설치

npm ci

 

-> dependency tree가 다시 계산되고 invalid 상태가 해결되면서 typecheck 문제가 해결됐다. 짠


npm install 대신 npm ci인 이유

npm ci

  • package-lock.json을 그대로 신뢰
  • 의존성 재해석 없음
  • lockfile 수정 없음
  • CI와 동일한 결과 보장

즉 npm ci는 재현 가능한 설치(reproducible install) 이다.

npm install

npm install을 하면 lockfile 재작성, dependency 트리 재조정, hoisting 결과 변경 등이 일어나기 때문에 디버깅 상황에서는 오히려 상태가 바뀔 수 있다.


Nx 캐시가 문제를 키우는 이유

Nx는 TypeScript project graph, dependency graph, 이전 typecheck 결과 등을 캐싱한다.

문제는 이 캐시가 이미 invalid 상태의 TypeScript 인스턴스 기준으로 만들어졌을 수 있다는 점이다. 그러므로 Nx 캐시 리셋을 해주자.

npx nx reset

 


정리

  1. peerDependencies는 호환성 계약
  2. npm의 peerDependency strictness 설정에 따라 dependency tree가 invalid가 될 수 있음
  3. 설정 바꾼 뒤에는 dependency 재설치 + Nx 캐시 리셋 하기