node_modules
없이 node
를 사용할 수 있는 환경인 yarn berry
를 알아보자.
npm, Yarn, pnpm 모두 역할은 대부분 동일하다.
따라서 설치 속도, 스토리지 사용량, 기존 워크플로우와 결합되는 방식 등을 고려해 패키지 매니저를 결정한다.
Language | Package Manager | Software Repository |
---|---|---|
Python | pip | PyPI |
PHP | Composer | Packagist |
Node.js | npm, Yarn, pnpm | npm, Yarn, pnpm |
Java | Maven, Gradle | Maven |
Ruby | RubyGems, Bundler | RubyGems, Bundler |
node.js 환경의 패키지 매니저로 크게 npm과 yarn, pnpm이 존재하며,
패키지 매니저의 기능은 동일하나 내부적인 차이점이 존재한다.
npm
, Yarn
: node_modules
폴더에 dependency 설치pnpm
: 중첩된 node_modlues
폴더에 dependency를 저장하는 방식을 개선하기 위한 개념 도입Yarn-berry
: PnP
(Plug'n'Play) 모드 (node_modules
X)Yarn Berry
는 Node.js
를 위한 새로운 패키지 관리 시스템이다.
Yarn v1
(Yarn classic
)에서 2020.01.25 정식 버전 Yarn v2
(Yarn Berry
)가 출시되었으며,
현재 Yarn Berry
는 Babel
을 비롯한 큰 오픈소스 레포지토리에서도 채택되어 사용 중에 있다.
위와 같이 NPM
은 Node.js
를 설치할 경우 기본적으로 제공되는 패키지 매니저이지만 비효율적이거나, 깨져 있는 부분이 많다.
패키지가 중복으로 설치될 수 있다는 단점 존재
의존성 검색의 비효율성
- 느린 I/O 호출의 반복 → 경우에 따라 I/O 호출의 실패로 이어진다.
환경에 따라 달라지는 동작
- 상위 디렉토리 환경에 따라 의존성 호출의 변수 발생
비효율적인 설치
- 매우 큰 node_modules
의 공간 차지
- node_modules
디렉토리 구조 구축을 위한 큰 비용의 I/O 작업
유령 의존성
node_modules
를 아끼기 위해 호이스팅 기법 사용 (NPM, Yarn v1)require()
할 수 있는 현상 : 유령 의존성package.json
의 수정에 따라 의존성 관리 시스템이 혼란스러워질 가능성 ⬆️Yarn Berry
는 위에서 언급한 NPM
의 "깨져 있는" 패키지 관리 시스템을 개선하고자
적은 공간의 사용, 효율적인 의존성 검색을 목표로 출시되었다.
node_modules
폴더의 특정 패키지를 검색할 경우 모든 패키지를 순회하며 해당 패키지 존재 여부를 찾는 방법은 매우 비효율적이다.
1. Node
가 패키지를 검색할 때 잘 찾을 수 있도록 도와주는 역할이 패키지 매니저의 일이라는 생각과
2. 패키지 매니저가 node_modules
디렉터리 구조를 만드는 것에 그치지 않고,
보다 근본적이며 안전한 방법으로 의존성을 관리하는 방법에 대해 고민한 결과
Plug'n'Play가 탄생했다.
Yarn Berry
에서는 node_modules
를 생성하는 대신 의존성 lookup 파일인 .pnp.cjs
를 생성한다.
.pnp.cjs
파일의 포함 내용
- 관련된 패키지 이름
- 패키지 버전
- 디스크에서의 위치
- 의존성 리스트
- etc.
Plug'n'Play
켜기
NPM
에서 최신 버전의 Yarn
을 내려받은 뒤, 버전을 Berry
로 설치해 Yarn Berry
를 사용한다.
$ npm install -g yarn
$ cd ../path/to/some-package
$ yarn set version berry
Yarn Berry
는 하위호환을 위해 패키지 단위로만 의존성 관리 시스템을 도입할 수 있다.
node_modules
를 생성하지 않는 Yarn Berry
는 의존성 정보를 .yarn/cache
폴더에 저장한다.
.pnp.cjs
파일에 의존성을 찾을 수 있는 정보가 기록되며, 해당 파일을 통해 Disk I/O 없이 어떤 패키지가 어떤 라이브러리에 의존하는지,
각 라이브러리가 어디에 위치하는지 바로 알 수 있다.
Yarn
은 Node.js
에서 제공하는 require()
문의 동작을 덮어씀으로써 효율적으로 패키지를 검색할 수 있도록 한다.
PnP API
를 이용해 의존성 관리를 하고 있을 경우 : yarn node
명령어를 사용 (node
명령어 X) Node.js
앱을 실행 시 package.json
의 scripts
에 실행 스크립트를 등록해 사용한다.
Yarn
으로 스크립트를 실행하면 PnP로 의존성을 자동으로 불러온다.
또한 Zip 아카이브로 의존성을 관리할 수 있는데 이를 사용할 경우,
없는 의존성이나 더 이상 필요없는 의존성을 쉽게 찾을 수 있다.
또한 Zip 파일의 내용이 변경될 경우 체크섬과 비교해 쉽게 변경 여부를 감지할 수 있다.
의존성 검색
- 의존성 검색 시 더 이상 node_modules
폴더의 순회가 필요 없다.
- .pnp.cjs
파일이 제공하는 자료구조를 이용해 의존성의 위치를 바로 찾는다.
- require()
에 걸리는 시간이 크게 단축된다.
재현 가능성
- 패키지의 모든 의존성이 .pnp.cjs
파일을 이용해 관리되기에 더 이상 외부 환경에 영향을 받지 않는다.
의존성을 설치할 때
- 설치를 위한 node_modules
디렉토리 생성이 필요없다.
- zero-install
사용 시 대부분의 라이브러리를 설치할 필요 없이 사용 가능하다.
- 같은 버전의 패키지가 여러번 복사될 필요가 없기에 설치 시간을 극단적으로 단축할 수 있다.
엄격한 의존성 관리
- node_modules
와 같이 의존성을 끌어올리지 않는다.
- 각 패키지가 자신이 package.json
에 기술하는 의존성에만 접근할 수 있다.
- 예기치 못한 버그를 일으키는 유령 의존성 현상을 막을 수 있다.
의존성 검증
- Yarn PnP
에서 Zip파일을 이용해 패키지를 관리하므로 의존성 관리가 용이하다.
- 의존성이 잘못되었을 때 쉽게 바로잡을 수 있다.
Zero-Install
Zero-Install
: Yarn Berry
에서 의존성을 버전 관리에 포함하는 것Yarn PnP
는 의존성을 압축 파일로 관리하므로 의존성 용량이 작다.Yarn install
을 실행하지 않아도 된다.Zero-Install
사용 시 .gitignore
파일 설정.yarn/*
!.yarn/cache
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/sdks
!.yarn/versions
여전히 PnP를 지원하지 않는 패키지 존재
프로젝트에 PnP를 지원하지 않는 패키지가 하나라도 존재한다면 PnP 방식일지라도 node_modules
가 따라온다.
각 모듈이 PnP로 사용될 수 있기 위해서는 PnP 방식에 맞게 의존성 관리가 strict하게 셋팅되어야 한다.
PnP loose 모드를 통해 명시적으로 요구하는 디펜던시를 요구하지 않도록 할 수 있다.
// .yarnrc.yml
pnpMode: loose
우선 PnP를 적용해 기존 npm
의 node_modules
디렉토리의 설치가 필요 없이
패키지 환경을 구축할 수 있다는 점이 가장 큰 매력이라고 생각하였다.
매번 npm
또는 yarn
으로 패키지 환경을 셋팅하면 git 상에서 clone을 받아 저장소의 코드를 사용할 때
npm install
및 yarn install
명령어를 통해 의존성을 관리해주었어야 했는데,
공간 차지 및 설치의 번거로움이 해소되었다는 점이 정말 유익하다고 판단된다.
Yarn Berry
를 아직 제대로 된 프로젝트에 도입해보지 않았기에, 관련된 단점을 구글링으로 찾을 수 밖에 없었는데
대부분의 단점 혹은 트러블슈팅은 아직 PnP를 지원하지 않는 패키지 또는 PnP-dependency와 관련된 부분이었다.
이러한 문제점은 직접 프로젝트를 통해 겪어보는 것이 어떤 방법 보다도 잘 이해할 수 있으리라는 생각이 들었고,
빠르게 Yarn Berry
셋팅을 해본 뒤 PnP를 적용해 본 패키지 매니저의 환경을 피부로 느껴보고자 한다.