⚽️ 목표
NPM vs Yarn Classic(v1) vs Yarn Berry(v2) vs PNPM
•
Yarn Classic과 Yarn Berry는 다르다는걸 인지하자.
◦
현시점(2022년 7월 22일) 기준으로 Yarn Classic은 기능 추가 또는 개선없이 관리만 진행되는 중 이다.
TL;DR
PNPM
•
점점 패키지 매니저들의 차이점이 희미해진다.
◦
pnp도 yarn berry, pnpm 둘다 있다.
◦
pnpm의 CAS를 yarn berry에서 채용하기로 확정했다.
◦
npm은 보안적으로 허점이 있었었다(과거 완료형)
▪
현재는 여러 방법(패키지 등록시 취약점 검사와 같은)으로 대응 완료됨.
•
yarn berry의 pnp(plug and play)는 이슈가 많다.
◦
현재 회사 프로젝트 기반으로 복잡하지 않게, 간단하게 “실행되냐?”의 기준으로 봤을때… 스토리북 부터 해서 많은 오류가 발생했다.
•
기존 구성된 npm 프로젝트에서 pnpm으로 이주 시 생긴문제 단 하나였다.
◦
storybook 관련 이슈였지만 아주 마이너한 이슈였다. → hoisting 되지않은 패키지로 인한 이슈였다. 해당 패키지를 간단하게 설치만해주니 완전 정상작동하였다.
•
pnpm도 설정으로 pnp 활성화가 가능하다.
◦
더욱더 yarn berry를 선택할 이유가 희미해진 계기다. yarn berry가 이제는 나에게 “굳이?”라는 관점으로 다가왔다.
1-1. npm과 Yarn classic(Yarn v1)
npm
“여러분 NPM은 Node Package Manager의 약자가 아닙니다” - 공식문서
•
2010년에 출시
•
NPM 이름은 Node Package Manager가 아닌 Node PM, New PM을 뜻한다.
•
처음엔 여러 이슈들이 있었으나 대부분 해결 된 상태
◦
lock 파일의 부재 → 설치할 때마다 조금 씩 바뀌는 버전들로인한 프로젝트 안정성 저하, 지금은 lock 파일 지원
•
패키지 관리자의 시작
◦
이전 JS 생태계에선 패키지를 모두 수동으로 설치 및 관리 했었다.
◦
npm의 등장으로 인해 패키지 출시 및 관리가 편의해진건 부정할 수 없는 사실이다.
Yarn classic (Yarn v1)
Yet Anoter Resource Negotiator
•
2016년에 페이스북 + 구글 + 기타등등이 출시한 새로운 패키지 관리자
•
npm과 똑같은 의존성 해결 방식을 채택함 → 여전히 비효율적인 패키지 의존성관리
•
출시 당시엔 npm에 비해 상대적으로 좋은 성능으로 관심을 받았었다. → 요즘은 npm이나 yarn v1이나.. 둘다 비슷비슷하다.
•
.lock 파일의 존재를 처음으로 만들었다. → 이후엔 npm에서도 .lock 파일을 제공
•
2020년 부터 maintenance mode가 됨 → 추가 기능 개발 없이 관리만 진행 중
yarn과 npm의 문제점
•
node_modules를 이용해 dependency를 관리한다.
•
중복된 똑같은 dependency가 많아→ 저장공간을 많이 차지하며 어쩔땐 같은 라이브러리를 메모리에 중복되게 인스턴스화 한다.
요즘은?
•
서로의 장점을 도입하고 변화해가면 사실상 npm과 yarn v1의 차이점은 크게 존재하지 않는다. 속도 대결 또한 엎치락 뒤치락.
1-2 pnpm
pnpm의 컨셉 사진
npm, Yarn v1의 평탄화된 node_modules
•
npm과 yarn classic은 중복된 라이브러리를 “그나마" 줄이기 위해 평탄화(으.. 군대용어)를 수행함
◦
flattened를 평타화로 번역했다. 어떻게든 번역하려 노력하는 내 자신이 조금 싫어졌다.
// 평탄화 전
라이브러리A/node_modules/libName
라이브러리B/node_modules/libName
// 평탄화 후
라이브러리A
라이브러리B
libName
Plain Text
복사
•
라이브러리 A, B 둘다 libName이란 패키지에 의존성을 가지고 있다.
•
A, B 각자의 node_modules 아래에 라이브러리을 가지고 있을 경우 디스크 공간의 낭비!
•
라이브러리 1을 라이브러리 A와 B와 같이 루트 디렉터리로 호이스팅 한다! →A와 B는 호이스팅된 1을 참조
◦
그렇다. 여기서도 호이스팅이 존재한다. 누가 JS 패키지 관리 툴 아니랄 까봐 호이스팅도 똑같이 따라한다.
◦
이로인해 유령 의존성이 생긴다. → 내가 설치하지 않은 라이브러리를 참조할 수 있게 되는 마법이 생기는것이다.
content addressable store
hardlink, softlink가 뭐에여?
•
모든(서로다른 프로젝트) dependency는 하나의 파일을 참조한다.
◦
사용자의 홈디렉터리 아래(~/.pnpm-store) 존재하는 저장 장소를 칭한다.
•
결과적으로 모든 dependency들은 CAS를 바라보고 있다, 같은 버전일 경우 똑같은 파일을 굳이 같은 파일을 또 설치하는게 아니라 CAS에 존재하는 파일들을 연결시켜주는 개념이라고 보면된다.
non-flat node_modules 디렉터리
pnpm 공식 홈페이지에 존재하는 non-flat node_modules 디렉터리
# pnpm 프로젝트
/node_modules
- 라이브러리 A (.pnpm과 symlink 되어있음)
- .pnpm
- 라이브러리 A (라이브러리 A의 hardlink된 파일)
Bash
복사
•
기본 설정으로는 평탄화가 수행되지 않아 유령 의존성이 아예 사라진다.
•
프로젝트의 node_modules에는 실제 파일이 아닌 각자 필요한 참조를 softlink로 연결 후 파일은 hardlink 시켜준다.
평탄화를 없애기위한 pnpm의 노력
•
npm, yarn이 가지고 있던 비효율적인 의존성 관리 방식을 해결 → content-addressable storage를 이용
•
npm, yarn은 실제 의존성 파일들은 node_modules에 존재하나 pnpm은 사용자의 홈디렉터리 아래(~/.pnpm-store)에 실제 dependency들을 저장 → pnpm의 node_modules들은 .pnpm-store로 링크로만 존재한다.
•
유령 의존성이 존재하며 실제 중복 파일들이 많이 존재하는 NPM의 node_modules보다 적은 용량 차지, 메모리에 중복된 인스턴스로 존재하지 않는다.
서로 닮아가는 패키지 관리자
•
yarn berry → content-addressable storage 도입 예정
•
npm → symlink를 활용한 node_modules 방식 도입 예정
•
pnpm → pnp 지원
•
사실상 다 거기서 거기가 되어가고 있다.
1-3 Yarn berry
•
2020년에 릴리즈 → 기존 Yarn과 전혀다른 코드베이스
PnP(Plug n Play)
•
다른 관리자들과 다르게 node_modules대신 .pnp.cjs를 생성 한다.
•
중첩된 node_modules와는 다르게 하나의 파일로 존재
◦
의존성 검색이 효율적으로 수행됨 → 빨라짐
◦
중첩된 파일구조인 node_modules를 순회하며 찾을 필요가 없다. → .pnp.cjs에 실제 패키지 저장 위치 바로 참조가능
◦
package를 검색한 후 거의 즉각적으로 페이지를 찾아갈 수 있게 됨
•
실제 패키지들은 프로젝트 디렉터리에 .yarn/cache/에 zip 파일로 존재 → 디스크를 차지하는 용량이 더줄어듬
•
pnpm과 같이 의존성 호이스팅이 이루어지지 않아 유령 의존성이 사라짐
Zero Install
•
기존 npm과 다른 패키지 관리자들은 브랜치를 바꾸거나 리포지터리를 당겨왔을 때 npm i, yarn install로 패키지들을 설치 → node_modules가 너무 무거웠기 때문에 리포지터리에 같이 업로드 불가
•
Yarn berry에서는 패키지가 zip 파일로 압축되어 존재하기 때문에 용량이 현저히 낮으며 + 중복된 패키지가 최소화됐으므로 기존 node_modules에 비해 용량이 매우 낮다 → 리포저터리에 업로드하여 사용 가능
•
브랜치를 바꾸거나 리포지터리를 새로 당겨왔을 때 install 없이 바로 사용 가능
2. Yarn berry 설치
3. node_modules가 설치될 경우
nodeLinker
•
실제 사이드 프로젝트에 yarn berry 이주 테스트를 진행했으나 node_modules가 남아있…다? 그거 없다고 자랑한거 아니였어?
•
홈디렉터리에 존재하는 .yarnrc.yml에 nodeLinkder: node-modules 부분을 제거(또는 pnp로 변경후 yarn install로 다시설치!
•
아-기다리고-기다리던 pnp.cjs 파일이 생성되는걸 드디어 확인할 수 있음
vite dev 모드 시작 시 생기는 node_modules
•
vite에서 제공하는 Dependency Pre-Building 기능
•
개발 모드에서만 사용되며 의존성 패키지들을 미리 전처리 → 빠른 속도를 위해
기타
zero-install시 git-ignore 사항
결론
요즘 패키지 관리자들은 서로 닮아가고 있는 중.
그럼에도 불구하고 pnpm, yarn berry 중 하나 골라 쓰면 좋을거같다.
•
아직 지원하지 않는 라이브러리(PnP, ZeroInstall) 때문에 아직까지 호환성 이슈가 존재(VSC... VSC... VSC, Storybook)
•
프로젝트에서 이주 시도 시 직접 마주친 문제만 5개정도 - 그에 반해 pnpm은 사소한 이슈 1개 정도?
•
Zero Install의 필요성을 잘느끼지 못했다. -> 오히려 pnpm의 content-addressable storage가 더 매력적으로 느껴졌음
•
pnp 기능은 pnpm에서도 옵션으로 활성화 가능하다.
•
본인은 pnpm으로 가겠다.