npm
으로 프로젝트를 진행 중 Yarn Berry
를 도입하게 되었다.
새로운 패키지 관리 시스템을 도입하게 된 배경과 과정 등을 정리해본다.
패키지 매니저란?
npm에 업로드된 노드 모듈을 패키지라고 하는데, 다양한 자바스크립트 프로그램이 패키지라는 이름으로 npm에 등록되어 있고, 패키지가 다른 패키지를 사용할 경우 의존 관계를 가지기도 한다.
이러한 패키지들을 사용하기 위해서는 다운로드, 설치, 업데이트, 의존성 관리, 제거 등 복잡한 상황들이 많이 생기는데
패키지 매니저는 이러한 과정들을 자동화하여 편리하고 안전하게 수행할 수 있도록 해준다.
npm
과 yarn(v1)
은 어떤 점이 다른가?그 동안은 npm
으로만 써왔는데, 이유는 딱히.. 처음 접한 것이 npm
이었다는 것?! yarn berry
로 변경하면서 npm
과 yarn
의 차이를 찾아보았다
node
개발 환경에서는 패키지 매니저로 npm
또는 yarn
을 사용하는데,
개발에 있어서 npm
과 yarn
, 이 둘의 차이는 크게 없다고 한다.
yarn
은 npm
의 부족한 부분들을 개선하기 위해 Facebook에서 개발되었다. Yarn
은 npm
이 사용하는 동일한 npm
구조에 의존한다. 따라서 패키지의 레지스트리에 대한 것은 바뀌지 않았고, 설치 절차가 바뀌었다고 생각하면 된다.
npm
의 부족한 부분들을 개선하기 위해 나온 yarn
!npm
이 먼저 나왔기 때문에 yarn
보다는 다운로드 수 및 점유율 측면에서 앞설 수 있고yarn
이 npm
의 부족한 점들이 개선되었다는 점이 다른 점이라고 할 수 있겠다.
Yarn Berry(=yarn(v2))
는 뭐야?npm
의 부족한 부분들을 개선하기 위해 나온 yarn(v1)
이지만,
npm
과 yarn(v1)
의 공통적인 문제점이 있었는데..
npm
문제점npm
은 파일 시스템을 이용하여 의존성을 관리하는데 node-modules
폴더를 이용하는 것이 특징이다. 하지만 이렇게 관리하면 의존성 검색은 비효율적으로 동작한다..😱
npm
은 패키지를 찾기 위해 계속 상위 디렉토리의 node-modules
폴더를 탐색하는데, 바로 찾지 못할수록 느린 I/O
호출이 반복된다.. 경우에 따라서는 I/O
호출이 실패하기도..😱😱
npm
은 패키지를 찾지 못하면 상위 디렉토리의 node-modules
폴더를 계속 검색하는데, 이로 인해 해당 패키지의 상위 디렉토리 환경에 따라 동작이 변하게 된다. 이럴 경우 해당 상황을 재현하기 까다로워지기 때문에 환경에 따라 동작이 변하는 것은 나쁜 징조이다..😥
간단한 패키지를 몇 개 설치하지 않아도 node-modules
폴더는 매우 거대해진다. 게다가 next.js
등과 같이 다양한 기능을 제공하는 프레임워크, 라이브러리를 사용하게 된다면 메가에서 기가 단위의 디스크 용량을 사용하게 될 것이다.. (현재 내 플젝은 next...)
그리고 이렇게 거대해진 node-modules
폴더를 탐색하려면 많은 I/O
작업이 필요하니.. 말해뭐해..ㅠ
게다가 이렇게 거대해진 node-modules
폴더는 복잡하기 때문에 설치가 유효한지 검증하기 어렵다..
결국 이런 구조에서 의존성이 잘 설치되어 있는지 검증하려먼 많은 수의 I/O
호출이 필요..
이런 문제로 인해 yarn(v1)
이나 npm
은 기본적인 의존성 트리의 유효성까지만 검증하고, 각 패키지의 내용이 올바른지는 확인하지 않는다 😱
yarn(v1)
이나 npm
은 중복해서 설치되는 node-modules
를 아끼기 위해 끌어올리기(Hoisting
) 기법을 사용한다.
이렇게 끌어올리기에 따라 직접 의존하고 있지 않은 라이브러리를 require()
할 수 있는 현상을 유령 의존성(Phantom Dependency)이라고 부르는데,
유령 의존성 현상이 발생할 때, package.json
에 명시하지 않은 라이브러리를 조용히 사용할 수 있게 된다. 또는 다른 의존성을 제거할 때 소리없이 같이 사라지기도 해서 의존성 관리 시스템을 혼란스럽게 한다..
Plug’n’Play
(PnP
)Yarn Berry(=yarn(v2)
)는 pnp라는 개념을 도입해서 이런 문제들을 해결한다.
node-modules
의 성능 문제node-modules
의 비효율적인 구조 등등yarn2
에서는 비효율적인 node_modules
대신에 .pnp.js
라는 파일을 생성한다
npm install -g yarn
Yarn PnP
은 의존성을 압축 파일로 관리하기 때문에 의존성의 용량이 작다. 또한 각 의존성은 하나의 Zip 파일
로만 표현되기 때문에 의존성을 구성하는 파일의 숫자가 npm
만큼 많지 않다.
이처럼 용량과 파일의 숫자가 적기 때문에 Yarn Berry를 사용하면 의존성을 Git으로 관리할 수 있는데, 이렇게 Yarn Berry에서 의존성을 버전 관리에 포함하는 것을 Zero-Install
이라고 한다. Zero-Install
을 사용하게 되면,
다른 의존성을 사용하는 곳으로 브랜치를 변경했을 때, 잊지 않고 의존성을 설치해주어야 했고, 경우에 따라 잘못된 의존성 버전이 사용되어 알 수 없는 에러가 발생하기도 했는데, Zero-Install
을 사용하면 이런 문제들이 해결된다.
Zero-Install
을 사용하면 Git Clon
e으로 저장소를 복제했을 때 의존성들이 바로 사용 가능한 상태가 되어, 의존성을 설치할 필요가 없다..gitignore
파일 설정# Zero-Installs 를 사용할 때
.yarn/*
!.yarn/cache
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/sdks
!.yarn/versions
이렇게 공부하고 실제 npm에서 yarn berry로 변경하면서 크게 어려운 점은 없었던 것 같다. (워낙 자료들이 훌륭해서..ㅎㅎ)
그리고 너낌상이지만 불필요한 npm i
을 하지 않아서 좋았고,
불필요한 파일들이 설치되지 않아서 보다 가벼운? 느낌이었다.
그리고.. 사실 yarn berry로 변경하게 된 이유는, 프엔 동료가 제안해서 해보자!하는 마음으로 시작했는데..
그 프엔 동료는 이런 것들을 너무나 잘 알고 아는 것도 많다!👍👍
덕분에 이것저것 적용해보고 공부하고 테스트해 볼 수 있는 기회가 많아져서 좋다!!! 너무나도!!👏👏
나도 보다 시야를 넓혀서 제안도 해보고 적용도 해보고 싶다!
참고
토스: node_modules로부터 우리를 구원해 줄 Yarn Berry
vercel에서 yarn2는 아직이라고 해서.. yarn1로 되돌리다가..
cat ~/.yarnrc.yml
> yarnPath: ".yarn/releases/yarn-berry.cjs"
rm -f ~/.yarnrc.yml
npm install -g 'yarn@1.22.1'
yarn -v
> 1.22.10