npm은 범용적으로 많이 사용되나 비효율적인 측면이 많다.
npm은 파일 시스템
을 사용해 의존성을 관리하는데, 예를들어 Users/test/dev/components
라는 폴더에서 require로 lodash라는 패키지를 불러오는 상황을 가정할때
require.resolve.paths()
를 사용해 검색하는데 npm은 해당 패키지를 찾기위해 아래처럼 계속 상위 디렉토리를 탐색한다.
일반적으로 이런 I/O 호출은 느리게 진행된다.
$ node
Welcome to Node.js v12.16.3.
Type ".help" for more information.
> require.resolve.paths('lodash')
[
'/Users/test/dev/components/repl/node_modules',
'/Users/test/dev/components/node_modules',
'/Users/test/node_modules',
'/Users/node_modules',
'/node_modules'
...
]
node_modules는 수백메가바이트 수준의 매우 큰 공간을 차지한다.
이로인해 복잡도는 올라가고 검증이 어렵다. 수백개의 패키지가 서로 의존한다면 node_modules의 디렉토리 구조는 매우 깊어질것이다.
npm 및 yarn v1은 중복설치를 막기위해 Hoisting기법을 사용한다.
아래 이미지를 보면 A(1.0)
과 B(1.0)
이 중복되기 때문에 Hoisting 하여 디스크 낭비를 방지한다.
하지만 이런 과정에서 기존에는 require할수 없었던 B(1.0)
을 불러올수있게 된다.
따라서 package.json에 명시되지않은 B(1.0)
을 package-1에서 가져올수있게되는 현상이 발생하고 이를 유령의존성이라 부른다.
yarn berry
는 위 문제를 Plug 'n' Play
전략으로 해결한다.
yarn v1은 package.json 기반으로 의존 트리를 생성하고 디스크에 node_modules 구조를 만든다.
따라서 의존성 관리가 불완전한 파일시스템이 아닌 보다 안전한 의존성 관리를 위해 시작됐다.
npm최신 버전에서 yarn을 내려받고 버전을 berry
로 설정하면 된다,
npm i -g yarn
cd ../path/to/some-package
yarn set version berry
yarn berry는 하위호환을 위해 패키지 단위로만 도입 할 수 있다
yarn berry는 node_modules를 생성하지않는 대신, .yarn/cache
폴더에 의존성 정보가 저장되고, .pnp.cjs
파일에 의존성을 찾을수있는 정보가 기록된다.
이는 디스크 I/O작업이 없이 빠르게 동작한다.
예를들어 react
패키지는 .pnp.cjs
파일에서 아래와 같이 나타난다
/* react 패키지 중에서 */
["react", [
/* npm:17.0.1 버전은 */
["npm:17.0.1", {
/* 이 위치에 있고 */
"packageLocation": "./.yarn/cache/react-npm-17.0.1-98658812fc-a76d86ec97.zip/node_modules/react/",
/* 이 의존성들을 참조한다. */
"packageDependencies": [
["loose-envify", "npm:1.4.0"],
["object-assign", "npm:4.1.1"]
],
}]
]],
yarn은 node가 제공하는 require문을 덮어씀으로 node명령어 대신 yarn node
명령어를 사용해야 한다
$ yarn node
.yarn/cache
폴더 내부에 각 의존성들은 zip파일로 관리된다.
이로인해
.pnp.cjs
파일이 제공하는 자료구조를 이용해 바로 의존성 위치를 찾기때문..pnp.cjs
파일로 관리되기때문에 외부환경에 영향을 받지않는다.node_modules에 비해 zip파일로 관리하기 때문에 용량이 매우 적고 git 으로 관리가능함.
이로 인한 장점으로
요약하자면
npm은 비효율적인 탐색, 의존성 중복으로 인해 매우 무겁고 복잡하여 의존성관리 및 검증이 힘들다.
yarn berry는 zip아카이브와 .pnp.cjs로 관리하기 때문에 순회 과정이 필요없고 매우 가볍고 의존성 관리 및 검증이 쉽다.
따라서 CI에서 많은 시간을 줄일수있고 의존성도 더 엄격하게 관리가 가능하다!
https://toss.tech/article/node-modules-and-yarn-berry
https://velog.io/@dev_jiminn/MonoRepo-with-Yarn-Berry