만족
[Nodejs] 더 작고 빠른 패키지 매니징을 위한 yarn berry 본문
[Nodejs] 더 작고 빠른 패키지 매니징을 위한 yarn berry
Nodejs Satisfaction 2023. 8. 12. 22:32yarn classic
yarn classic(v1) 과 npm에서 의존성을 추가하면 node_modules 에 설치된다.
새로운 프로젝트를 생성하고, yarn init 으로 초기화한 후 yarn add react 를 이용해 react 의존성을 추가하면
node_modules에 react 패키지가 추가된 모습을 볼 수 있다.
그런데 분명 추가한 것은 react 하나뿐이지만, js-tokens 와 loose-envify 패키지도 존재하는 것을 확인할 수 있다.
node_modules/react/package.json의 dependencies를 살펴보면 loose-envify를 사용하고 있고,
node_modules/loose-envify/package.json의 dependencies를 살펴보면 js-tokens를 사용하고 있다.
기본적으로 프로젝트에 추가된 의존성들은 node_modules에 설치되는데,
node_modules 내에 있는 패키지의 중복 설치를 막기 위해 의존성 호이스팅이 발생한다.
require() 했을 때 탐색 순서가 우선적으로는 상위 디렉터리 방향으로 정해지기 때문에
패키지 위치를 위쪽(node_modules/react/node_modules가 아닌 node_modules)으로 이동시키는 것이다.
require.resolve.path()를 이용해 require()를 사용해 의존성을 불러올 때 탐색 순서를 살펴볼 수 있다.
require('react')를 했을 때
/Users/namgung-geon/cyphers-supporter-user-web/repl/node_modules 에서 react가 있는지 찾고
없다면 /Users/namgung-geon/cyphers-supporter-user-web/node_modules 에서 react가 있는지 찾고
없다면 /Users/namgung-geon/node_modules에서 react가 있는지 찾고
....
마지막으로 없다면 /Users/namgung-geon/.nvm/version/node/v16.19.1/lib/node_modules에서 react가 있는지 찾는다는 것이다.
의존성 호이스팅이 node_modules의 크기는 줄여주고 있지만
반대로 require 시 계속해서 module을 찾기 위해 비효율적인 Disk I/O를 발생시키고 있다.
더 작은 사이즈로 더 빨리 모듈을 찾을 수는 없을까?
yarn berry
yarn berry에서 등장한 pnp(plug and play) 개념에서는 의존성의 위치를 미리 지정하고
필요한 의존성 패키지들을 압축해서 저장한다.
따라서 yarn classic 에서 처럼 상위 디렉터리로 이동하면서 일일이 node_modules 를 뒤질 필요가 없다.
예컨데 다시 require('react')하는 상황을 재현해보면
이미 의존성의 위치를 알고 있으므로 한 번만 탐색하면 바로 찾을 수 있는 것이다.
이제 yarn berry와 pnp를 적용해 보자.
yarn set version berry
위 스크립트를 실행시키면 .yarn 폴더와 .yarnrc.yml 파일이 생성되었을 것이다.
nodeLinker: node_modules
yarnPath: .yarn/releases/yarn-3.6.1.cjs
.yarnrc.yml 파일에서 nodeLinker가 위와 같이 node_modules로 되어 있다면 pnp로 변경해 준다.
(pnp 모드에서는 의존성/버전 오류 등에 대해 좀 더 엄격한 듯 하다)
nodeLinker: pnp
yarnPath: .yarn/releases/yarn-3.6.1.cjs
이제 yarn 커맨드를 사용해 모듈을 설치해 준다.
이제 의존성 패키지들이 압축 파일로 모두 설치된다.
여기서 .pnp.cjs를 살펴보면
각 패키지들의 위치가 명시되어 있는 것을 확인할 수 있다.
따라서 이제 require가 더 빠르게 동작할 수 있게 되었다.
모듈이 압축 저장되기 때문에 사이즈도 크게 줄어들었다.
이런 방식을 사용했을 때 또 하나의 장점은 zero install이 가능해진다.
일례로 node_modules를 직접 설치해야만 하는 기존 방식에서는
새로운 환경(협업 환경 또는 CI 로 빌드/자동화 할 때)에서 실행할 때 마다 node_modules 를 모두 설치해야만 했다.
그러나 pnp방식을 사용할 경우 .yarn/cache에 작은 사이즈로 패키지를 저장하기 때문에 새로 설치할 필요가 없다.
vscode에서 비정상 작동할 경우
yarn dlx @yarnpkg/sdks vscode
pnp모드에서 일부 모듈(typescript, eslint, prettier 등)이 비정상 작동할 경우 위 명령어로 sdk를 설치한다.
Migration: yarn classic to yarn berry(pnp)
현재 프로젝트에서는 github action을 이용해 CI/CD를 구현해 두었다.
install modules (yarn install 실행) 에 30s 정도의 시간이 소요되고 있으며
이것은 매 액션 실행마다 낭비되는 시간이다.
yarn berry의 zero install 을 사용하면 이 시간을 아낄 수 있다.
위에서 설명했던 대로 yarn set version berry 실행과 .yarnrc.yml 파일을 수정하여 마이그레이션을 진행한다.
실제 프로젝트에서는 더 극적으로 패키지 사이즈가 차이가 난다.
거의 1/10 수준으로 줄어들었으며, 이마저도 CI/CD 환경에서 재설치할 필요가 없어졌다.
Lifecycle scripts
yarn classic에서는 스크립트 앞에 'pre'를 붙이면 스크립트 실행 전에, 'post'를 붙이면 실행 후에 실행할 스크립트를 추가할 수 있었다.
그러나 yarn berry부터는 일부 스크립트에서만 가능하도록 변경되었다.
https://yarnpkg.com/advanced/lifecycle-scripts
pre, post 접두사를 사용하고 있다면 package.json 수정이 필요하다.
참고
https://toss.tech/article/node-modules-and-yarn-berry
https://beomy.github.io/tech/etc/yarn-berry/
https://yarnpkg.com/getting-started/migration
https://kasterra.github.io/setting-yarn-berry/
'Nodejs' 카테고리의 다른 글
[Nodejs] file의 birthtime과 mtime (0) | 2024.10.11 |
---|---|
[Nodejs] pm2로 nodejs 데몬 프로세스 관리하기 (0) | 2023.03.13 |
[Nodejs] 커맨드 동시 실행으로 커밋 검사 속도 향상 (0) | 2023.01.22 |
[Nodejs] husky 를 이용한 Githook 추가 (0) | 2022.05.23 |
[Nodejs] jest를 이용한 테스트 코드 작성 (0) | 2022.05.23 |