참고 사항
- 회사에서
shell/sdk
라는 자체 개발 패키지를 사용 중(사내 플랫폼 연동용 SDK 라이브러리이며 문제의 원인) - 패키지 매니저:
Yarn berry(v3.4.1)
문제
- 회사에서 자체 개발하여 사용 중인
shell/sdk
패키지를0.0.18
에서0.0.21
로 버전 업데이트 후 앱을 실행하면 아래와 같은 오류가 발생

원인
- 외부 패키지인 shell/sdk와 개발 중인 프로젝트에서 서로 다른 버전의 react를 사용해서 발생한 문제

해결 방법
- react 패키지를 어떤 버전으로 사용할 것인지
package.json
의 resolutions 필드에서 정의해준다.- resolutions 필드에 패키지 버전을 명시하면 프로젝트 내 모든 패키지가 특정 버전을 선택하도록 강제할 수 있다.
"resolutions": {
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
이후에 yarn install을 수행하면, 아래와 같이 shell/sdk
의 react 버전이 focus-fe
와 동일한 버전으로 설치된다.
focus-fe@workspace로 표시된 것으로 알 수 있듯, 현재 팀에서 개발 중인 프로젝트 이름이 focus-fe 이다.

- 혹은
yarn.lock
파일과yarn cache clean
으로 기존 패키지를 제거하고, 새로yarn install
한다.- 이 방식을 선택하면,
focus-fe
의 react의 패키지 버전이 최신 버전으로 업데이트 된다.
- 이 방식을 선택하면,

- 혹은 그냥 react 버전을 업데이트 해주면 된다.
심층 원인 파악: 두 방식의 차이는 무엇인가?
→ lock 파일의 존재 의의를 알아야 한다.
https://classic.yarnpkg.com/en/docs/yarn-lock/
yarn.lock
은 현재 설치된 패키지의 의존성과 패키지 버전을 명시한 파일이다. package-lock.json
도 마찬가지
문제가 발생하기 이전으로 돌아가 프로젝트의 yarn.lock
에서 react 버전을 확인해보면 아래와 같다.

프로젝트에서 react는 버전 18.2.0
으로 설치되어 있다.
이제 문제가 발생할 당시의 @shell/sdk
의존성을 확인해보았다**.**
shell/sdk
의 버전을 0.0.18
버전에서 0.0.21
버전으로 업데이트한 상황이다.

react@^18.3.1
을 의존성으로 명시되어 있다.
그리고 lock 파일에서 react를 확인해보면 아래와 같이 두 개 버전의 react가 설치되어 있음을 확인할 수 있다.

yarn cache
폴더를 확인해보니 이렇게 react@18.3.1 버전의 패키지가 설치되어 있었다.

yarn why react
로 react 패키지의 의존성 트리를 간략하게 확인해보았다. react의 의존성 버전이 서로 다르다.

이처럼 여러 버전의 react가 있을 경우, 특정 패키지가 현재 프로젝트와 다른 버전의 react를 참조할 때 충돌이 된다.
솔루션 분석
이제 yarn.lock 파일을 제거하고 재설치를 진행해보자. install 전에 yarn cache clean
도 진행한다.
확인해보면 설치된 react 버전이 18.3.1임을 확인할 수 있다.


작성일 기준 가장 최신 react 버전은 18.3.1 이므로, yarn 패키지 매니저가 18 메이저 버전 이내 가장 최신 패키지를 설치했음을 확인할 수 있다.
https://github.com/facebook/react/releases

yarn은 패키지를 설치할 때, 패키지 종속성과 최신 패키지 버전을 고려하여 설치할 패키지의 버전을 선택한다. ^
은 메이저 버전은 유지하고 마이너 버전 이하에 대해서만 업데이트 하므로, 최신 버전인 react@18.3.1
역시 ^18.2.0
범위에 해당한다.
→ 따라서 lock 파일을 제거하고 yarn install을 수행하면, 패키지 매니저는 프로젝트들의 버전과 종속성을 모두 고려하여 최신 패키지 버전을 resolution 한다.
https://www.geeksforgeeks.org/difference-between-tilde-and-caret-in-package-json/
그렇다면 @shell/sdk
패키지를 업데이트 했을 때, react 패키지가 업데이트 되지 않고 추가 설치되는 이유는 무엇일까?
→ 근본적인 원인은 @shell/sdk
패키지를 만든 제작자가 external로 react를 명시하지 않았기 때문이다. 따라서 이러한 이슈는 사내 자체 개발한 패키지를 사용하는 등 매우 특수한 상황에서 겪을 수 있는 이슈라고 할 수 있다.
패키지 업데이트 이전에 **shell/sdk
**가 사용한 react 버전을 확인해보면, 18.2.0
인 것을 알 수 있었다.


이제 yarn up @shell/sdk@0.0.21
로 업데이트해보았다.
fetch step에서 react@18.3.1
을 새로 설치하고 있음을 콘솔에서 확인 가능하다.

이미 기존 프로젝트에서 react@18.2.0
을 사용하며 해당 버전의 react를 의존성으로 패키지들이 관리되고 있는 상황에서 새로 업데이트하는 0.0.21 버전
의 shell/sdk
는 18.3.1 react 버전을 의존성으로 하기 때문에 패키지 매니저는 기존 react 버전을 업데이트하는 것이 아닌, 새로운 버전의 react를 추가 설치하고 있는 상황이다.
프로젝트는 react@18.2.0
을 필요로 하고, shell/sdk
는 react@18.3.1
을 필요로 하는 것이다. (즉, 둘 다 필요하다고 패키지 매니저는 인식하고 있다.)
다시 강조하지만, 외부 패키지 제작자가 external로 react를 명시해야 했음에도 그러지 않았던 것이 문제의 원인.
package.json
에서 resolutions
필드에 버전을 명시하고 yarn up @shell/sdk@0.0.21
를 수행하면 fetch step에서 해당 문구는 사라진다. 이미 shell/sdk
의 의존성으로 18.2.0 버전의 react가 resolution 되기 때문이다. 해당 버전의 react는 이미 cache 에 등록되어 있으므로 새로 설치되지 않는다.(이 프로젝트는 Yarn berry를 사용하고 있음에 유의, 패키지 매니저에 따라 패키지 버전을 resolution하는 필드 명이 다르다.)
정리
package.json에서 resolutions 필드를 이용한 방식은 프로젝트 내 새로운 패키지를 설치하거나 업데이트할 때 해당 패키지의 의존성을 resolutions 필드에서 정의한 버전으로 강제하는 방식이다.
https://classic.yarnpkg.com/lang/en/docs/selective-version-resolutions/
lock 파일 삭제 후 재설치는 프로젝트에서 이전에 설치한 패키지들의 버전과 의존성들을 새롭게 변경하여 적용하는 방식이며, 패키지 매니저에 따라 package.json에 명시한 버전 이내 패키지 버전 업데이트도 이루어질 수 있다. 이때 yarn.lock
파일이 변경되었으므로, 해당 커밋을 pull받은 다른 팀원은 yarn install을 수행해야 한다.