yarn berry가 무엇인지 알아보고 장점과 단점을 파악해보자!
🤔 yarn berry가 뭐야?
- Yarn Berry는 Node.js를 위한 새로운 패키지 관리 시스템.
- 기존의 npm, yarn v1 의 패키지 비효율적인 매니징 방법을 개선함.
😨 기존 NPM의 문제점
- lock 파일이 없다보니 생기는 패키지의 버저닝/의존성 이슈
- ex) 의존성이 커서 수백 개의 파일 중 단 몇 줄의 코드만 삭제해도 동작하지 않음.
- 보안 이슈
- 오픈소스 공유플랫폼 npm에서 컴퓨터에 백도어를 설치하는 악성코드가 포함된 자바스크립트 라이브러리가 발견.
- 백도어(backdoor)란 어떤 제품이나 컴퓨터 시스템, 암호시스템 혹은 알고리즘에서 정상적인 인증 절차를 우회하는 방법론을 뜻함.
- 다른 패키지가 즉시 포함될 수 있도록 하는 코드를 자동으로 실행. 필요하지 않은 코드도 같이 실행.
- 패키지가 늘어날 수록 성능 저하가 발생.
⇒ 위의 문제들을 해결하고자 2016년, Facebook을 중심으로 Google, Exponent, Tilde 회사들과 함께 기존에 있었던 npm 의 문제를 해결해보고자 새로운 패키지 매니저인 yarn을 발표함.
🤩 yarn v1의 장점
- yarn.lock파일 자동 생성. 어느 환경에서든 동일한 패키지를 설치하게 함.
- 의존성 트리 이슈는 lock파일과 설치 알고리즘을 통해 개선.
- 패키지 병렬 설치를 통한 성능 개선.
- cache directory를 통한 오프라인 미러링과 left-pad 이슈 방지.
- directory의 캐시를 오프라인에서도 그대로 쓸 수 있는 걸 말하는 듯?
😰 그래도 해결하지 못했다!?
npm과 yarn v1의 공통적인 문제점.
- node_modules의 거대함과 depth의 문제.
- 간단한 패키지를 설치해도 node_modules의 depth와 용량은 커짐.
- next.js등과 같이 다양한 기능을 제공하는 프레임워크, 라이브러리를 사용하게 된다면 최소 몇백메가에서 기가 단위의 디스크 용량을 사용하게 됨.
- depth는 점점 깊어지고 설치, 삭제, 수정, 실행 등의 속도에 영향을 끼침.
- 패키지의 내용은 확인하지 못하고 기본적인 의존성 트리만 검증함.
- 의존성 트리란 이렇게 의존 관계이지만 흩어져있는 앱 내의 상태들 혹은 클래스들을 예쁜 트리형태로 만들어주는 것.

- 유령 의존성(Phantom Dependency).
- 직접 의존하고 있지 않은 라이브러리를 require() 할 수 있는 현상을 유령 의존성(Phantom Dependency)이라고 부름.
- 예를 들어 왼쪽 그림을 보면 package-1에서 B (1.0)패키지를 가져다 쓸 수 없는 구조지만 오른쪽 그림을 보면 Hoisted가 되면서 package-1이 B (1.0)을 설치한 적이 없지만 B (1.0)을 가져다 쓸 수 있게 됨.
- 유령 의존성 현상이 발생할 때, package.json에 명시하지 않은 라이브러리를 조용히 사용할 수 있게 됨. 다른 의존성을 package.json 에서 제거했을 때 소리없이 같이 사라지기도 함. 이런 특성은 의존성 관리 시스템을 혼란스럽게 만듦.

😍 yarn berry(v2)의 등장
- yarn berry(v2)에서는 pnp라는 개념을 도입함 → node_modules 대신 .pnp.js라는 파일 생성.
패키지 이름
+패키지 버전
+패키지의 실제 위치
를 담은 맵과,패키지 이름
+패키지 버전
+패키지의 종속성
을 담은 맵을 저장.
["@ant-design/react-slick", [ //패키지 이름 ["npm:0.28.3", { //패키지 버전 //패키지 경로 "packageLocation": "./.yarn/cache/@ant-design-react-slick-npm-0.28.3-ece1f2feb7-887cb395bd.zip/node_modules/@ant-design/react-slick/", "packageDependencies": [ //패키지 종속성 ["@ant-design/react-slick", "npm:0.28.3"], ["@babel/runtime", "npm:7.14.6"], ["classnames", "npm:2.3.1"], ["json2mq", "npm:0.2.0"], ["lodash", "npm:4.17.21"], ["resize-observer-polyfill", "npm:1.5.1"] ], "linkType": "HARD", }] ]],
무슨 장점이 있을까?
- .pnp.js파일 하나만 생성하게됨으로서 설치가 빨라짐.
- disk I/O사용이 줄어들기 때문에 안정적으로 설치 가능. (특히 윈도우에서)
- 입력(Input)/출력(Output)의 약자로, 컴퓨터 및 주변장치에 대하여 데이터를 전송하는 프로그램, 운영 혹은 장치를 일컫는 말.
- 종속성 트리의 최적화 및 예측가능한 패키지 인스턴스화.
- Zero-Installs의 부분으로서 repository에 .pnp.js를 commit할 수 있음(의존성을 버전관리에 포함).
- 다른 환경에서도 별도의 yarn install을 통한 설치가 필요없도록 repository에 commit을 하도록 요구.
- CI에서 의존성 설치하는 시간을 크게 절약. 빌드와 배포 시간을 크게 단축.
💡 커밋하는 데 오래걸리지 않을까? node_modules 는 1.2GB 크기이고 13만 5천개의 파일로 구성되어 있는 반면, Yarn PnP의 필요한 패키지들은 139MB 크기의 2천개의 압축 파일로 구성됨.
- 의존성을 검색할 때, 더 이상 node_modules 폴더를 순회할 필요가 없음. .pnp.cjs 파일이 제공하는 자료구조를 이용하여 바로 의존성의 위치를 찾기 때문. 이로써 require()에 걸리는 시간이 크게 단축.
- Yarn PnP는 node_modules에서와 같이 의존성을 끌어올리지 않음 (엄격한 의존성 관리). 이로써 각 패키지들은 package.json에만 의존. → 예기치 못한 버그(환경에 따라 우연히 작동)를 일으키던 유령 의존성 현상 막음.
- Yarn PnP에서는 Zip 파일을 이용하여 패키지를 관리함. 따라서 빠진 의존성을 찾거나 의존성 파일이 변경되었음을 찾기 쉬움. 의존성이 잘못되었을 때 쉽게 바로잡을 수 있음.
- ex) Recoil 0.1.2 버전은
recoil-npm-0.1.2-9a0edbd2b9-c69105dd7d.zip
과 같은 압축 파일로 관리.
😋 사용해보자!
$ npm install -g yarn$ cd ../path/to/some-package //하위호환을 위해 패키지 단위로만 도입할 수 있음.$ yarn set version berry//ts 사용시$ yarn init -2$ yarn dlx @yarnpkg/sdks vscode

궁금한 것
- packag.json이 아닌 lock 파일로 관리하는 이유
- package.json (패키지 파일) : 모든 패키지가 의존하고 있는 이름과 버전 나열. 패키지 매니저로 node-modules 생성(npm, yarn v1)
- lock 파일 : 패키지 버전이 달라짐에 따라 각자 개발 환경에서 버전이 다른 문법을 사용하는 것을 방지하기 위해 버전을 잠금시킨 것.
- 왜 이 둘을 나누냐하면! 용도가 다르니 분리한 것 + package.json 만으로는 역량이 부족함.

- yarn.lock과 .pnp.js의 차이 그리고 package.json
- P’n’P 랑 yarn.lock 은 해결하는 문제 영역이 다름.
- lock : 파일 잠금
- pnp : module resolution 에 대한 인덱싱
- Pnp 란 : Defines what linker should be used for installing Node packages (useful to enable the node-modules plugin), one of:
pnp
,pnpm
andnode-modules
. - pnp.js는 node_modules를 대신하는 역할이라 캐싱을 위한 부분.
- package.json : 표준 패키지 매니페스트

참고자료 :