yarn berry는 npm과 함께 js 패키지매니저 쌍두마차인 yarn의 버전 2이다. (yarn v1은 yarn classic이라고 많이들 부르는것 같다.) 기존 npm과 yarn v1이 가지고 있는 문제들에 해결책을 제시한다.
node_modules폴더에서 모듈을 불러올때, require() 함수를 호출해 모듈을 찾을때까지 상위 node_modules 디렉터리를 순회하게 된다. 매 depth 마다 느린 연산이 반복된다. (디스크가 readdir,stat 같은 느린 I/O동작을 하게 된다.)
따라서 프로젝트의 의존성 트리가 깊어지면, 패키지 다운로드 및 빌드 시간이 늘어난다. 의존성이 잘 설치되어있는지 검증하기도 어렵다.
node_modules의 크기는 매우크다. 느린 컴퓨터의 경우 긴 패키지 리스트 설치시간으로 인해 지옥을 경험한다.(필자는 수명이 다한 노트북을 통해 경험해 보았다.)
왼쪽에서처럼 의존성 중복 방지를 위해서 npm과 yarn v1은 Hoisting 기법을 통해 오른쪽과 같이 패키지들을 끌어올려두는데 이렇게 두면 package.json에 명시해 두지 않은 패키지 B를 사용할 수 있게 된다.만약 패키지 B를 사용할 경우 패키지 A를 삭제하면 B를 사용하지 못하게 되므로 예기치 못한 오류가 발생(side effect)하게 된다.
Yarn Berry는 패키지의 압축 파일을 .yarn/cache 폴더에 수평적으로 저장한다. 이 방식을 Plug'n'Play(PnP)라고 한다. 압축 파일은 ZipFS를 이용하여 해당 모듈 로드가 필요할 때 압축을 해제하여 접근한다.
빠른 의존성 검색 : node_modules를 생성하지 않고 의존성이 .yarn/cache에 수평적으로 저장되고, .pnp.cjs 파일에 의존성을 찾을 수 있는 정보가 기록된다, 따라서 모든 패키지에 대한 접근 시간이 O(1)이 된다. 따라서 require()에 소요되는 시간이 크게 단축된다.
빠른 설치&삭제 + 작은 저장 공간 : 압축 파일 단위로 설치되기 때문에 의존성을 구성하는 파일의 수가 절대적으로 감소한다. 여기에 zero-install 전략을 사용하면 아예 설치 과정을 생략할 수 있다.
유령 의존성 방지 : 호이스팅을 사용하지 않기 때문에 의도하지 않은 의존성이 발생하지 않는다. 엄격하게 의존성 관리를 할 수 있다.
의존성 검증 : 의존성 유실,변경 트래킹이 쉽다. 따라서 의존성 폴더 전체를 지우고 다시 설치해야 하는 경우를 방지 할 수 있음.
$ npm install -g yarn
$ cd ../path/to/some-package
$ yarn set version berry
각 패키지는 버전마다 하나의 Zip(스토리지 용량을 크게 아낄 수 있다.) 아카이브만을 가진다.
용량이 작으므로 /.yarn/cache 폴더를 git에 그냥 올려두고 리포지토리를 clone했을 때 패키지 설치과정을 스킵하도록 할 수 있다. 이를 통해 CI시 의존성 설치에 시간을 크게 줄일 수 있다.
참고
https://d2.naver.com/helloworld/7553804
https://toss.tech/article/node-modules-and-yarn-berry