소개
Node 생태계에서 사용 가능한 3가지 패키지 매니저를 소개하고자 합니다.
NPM이란?
YARN이란?
PNPM이란?
각각의 패지키 매니저의 특징, 장단점등을 통해서 어떤 패키지 매니저를 선택할지를 가이드해보고자 합니다.
NPM이란 무엇인가?
NPM(Node Package Manager)의 약자로, Node.js 공식 패키지 매니저입니다.
프로젝트에 필요한 외부 라이브러리를 설치, 삭제, 리스트업할 수 있습니다.
프로젝트 패키지 관리를 위해서 package.json과 package-lock.json을 사용합니다.
설치
Windows 11
choco install nodejs --version=20.11.1
Mac
brew install node@20.11.1
NPM의 모듈 알고리즘 단점
npm은 기본적으로 평탄화된 알고리즘을 사용합니다.
평탄화된 종속성으로 다음과 같은 문제가 발생 가능합니다.
종속성 트리를 평탄화화는 알고리즘은 복잡하며, 일부 패키지는 다른 패키지의 node_modules 폴더 내로 복제됩니다.
본인이 의존하는 패키지에 엑세스할 수 있습니다.
A 모듈을 설치했고 A 모듈이 B 모듈을 설치한다고 생각해봅시다.
그런데 루트 경로에서 B 모듈을 임포트하여 사용할 수 있습니다.
YARN이란?
YARN(Yet Another Resource Negotiator)은 Node 패키지 관리 매니저입니다.
속도, 안정성, 보안과 같은 NPM의 일부 문제와 제한사항을 해결하도록 설계되었습니다.
프로젝트 패키지 관리를 위해서 package.json과 yarn.lock을 사용합니다.
YARN은 1.0 버전에서는 YARN Classic으로 불렸으나, 2.0 이후에는 YARN Berry로 불리고 있습니다.
설치
YARN Install
npm i yarn -g
YARN Berry
npm i yarn -g yarn set version berry
YARN의 모듈 알고리즘 장점
YARN Classic과 이에서 발전한 YARN Berry모두 NPM보다 나은 장점을 가지고 있습니다.
전체적으로 Cache 전략의 도입 및 로컬 공유 폴더를 이용한 방식들로 구성되어 있습니다.
Yarn (Blog) | Cache Strategies(Offline Mirror,Zero-Install)
Yarn (Blog) | PnP, Plug'n Play
다음과 같이 총 3가지 이유를 통해서 YARN이 NPM보다 좋은 이유를 찾을 수 있습니다.
Offline Mirror
모듈을 처음 설치 할 때, 컴퓨터는 NPM Registry를 사용하여 모듈에 접근합니다.
하지만 NPM Registry에 문제가 생기면, 이를 해결하기가 어렵습니다.
경량 Node.js 비공개 프록시 레지스트리인 Verdaccio를 사용하여, npm 레지스트리를 카피하여 사용할 수 있지만, 이 경우 개발자와 CI/CD 파이프라인에게 높은 복잡성을 초래합니다. 또한 이 방식은 중대한 보안 취약점을 만들기도 합니다.
Yarn은 enableGlobalCache옵션을 활성화하여, 설치된 레지스트리 항목을 Git에 업로드할 수 있는 형태로 변환하여 .yarn/lock파일에 저장할 수 있습니다.
즉, 별도로 구성된 Offline Mirror를 통해서, NPM Registry에 문제가 생겨도 모듈 다운로드가 가능합니다.PnP(Plug'n Play)
NPM과 YARN Classic(초창기)는 모두 node_modules를 생성합니다.
하지만 PnP를 사용하면 시스템에 지정된 경로에 모듈을 설치하고 프로젝트 경로에는 .pnp.cjs 파일을 생성합니다. 이 파일은 require, import 구문에 대해서 시스템 경로의 파일에 접근하도록 만들어줍니다.설치 공간 최소와 :
디스크 간 공유 설치 : 코드 아티펙트(캐싱된 빌드 에셋)를 공유
완벽하고 정확한 호이스팅 : 패키지 중복을 방지하기 위한 호이스팅
고스트 종속성 보호 : 루트 프로젝트에 설치되지 않은 모듈에 대한 접근 방지
시맨틱 오류 : NPM, YARN Classic 보다 더 디테일한 오류 메세지 출력
Zero-Install
브런치를 전환할 때, 실행에 대한 생각을 건너띌 수 있는 Yarn 기능들의 조합
Offline Mirror와 Plug'n Play를 결합하여 사용할 수 있는 방법입니다.
YARN의 단점
바로 위에서 말씀드린 3가지 장점에도 불구하고 YARN은 한 가지 치명적인 단점이 있다.
바로 YARN 에서는 NPM의 모든 모듈이 지원되지 않을 수 있다는 점이다.
물론, YARN Berry의 등장 이후 많은 NPM Maintainer들이 YARN에도 배포를 하고 있기 때문에 이 문제는 빠르게 해결 되고 있다.
PNPM이란?
PNPM(Performant Node Package Manager)
프로젝트 패키지 관리를 위해서 package.json과 pnpm-lock.json을 사용합니다.
설치
ynpm i pnpm -g
PNPM의 모듈 알고리즘의 장점
PNPM은 하드 링크(Hard Link)와 소프트 심볼릭 링크(Soft Symbolic Link)를 동시에 사용하여, 공유 디렉토리에 파일을 설치합니다.
프로젝트 경로에서 bar@1.0.0과 foo@1.0.0을 설치한다고 생각해봅시다.
아 경우 PNPM은 공유 디렉토리에 bar@1.0.0, foo@1.0.0을 설치합니다. 추후 프로젝트 경로에서 공유 디렉토리에 설치된 두 모듈로 하드 링크를 걸어서 모듈을 가져 옵니다.
하지만 특정 모듈의 하위 종속성 혹은 순환 종속성이 필요하면 어떻게 될까요?
만약 bar@1.0.0이 qar@2.0.0이 필요하다고 생각해봅시다.
또한 foo@1.0.0이 bar@1.0.0과 qar@2.0.0이 필요하다면, bar@1.0.0과 foo@1.0.0의 내부 종속성 모듈들은 소프트 심볼릭 링크를 통해서 가져옵니다.
node_modules
├── foo -> ./.pnpm/foo@1.0.0/node_modules/foo
└── .pnpm
├── bar@1.0.0
│ └── node_modules
│ ├── bar -> <store>/bar
│ └── qar -> ../../qar@2.0.0/node_modules/qar
├── foo@1.0.0
│ └── node_modules
│ ├── foo -> <store>/foo
│ ├── bar -> ../../bar@1.0.0/node_modules/bar
│ └── qar -> ../../qar@2.0.0/node_modules/qar
└── qar@2.0.0
└── node_modules
└── qar -> <store>/qar
상용 커맨드 모음
결론
전체적으로 개발팀의 규모가 작고 GitHub Action을 사용하는 경우에는 NPM을 그대로 사용해도 좋을 것 같습니다.
하지만 개발팀의 규모가 커지면서 Jenkins 등의 배포 전용 서버가 있는 경우에는 YARN, PNPM을 고민하는 것이 좋아보입니다.
구체적으로는 YARN은 그 스크립트가 NPM과 상이하기 때문에, PNPM이 더 좋은 선택으로 보입니다.
다만, PNPM에서 지원하지 않는 모듈이 필요한 경우는 미리 PoC를 반드시 진행하고 필수적인 라이브러리라면 YARN이나 NPM을 사용해야 할 수도 있습니다.
Feature | NPM | YARN | PNPM |
---|---|---|---|
Speed | Slow | Fast | Faster |
Disk Space | High | Low | Lower |
Security | Low | High | Higher |
Compatibility | High | Medium | Medium |
Popularity | High | Medium | Low |
Ecosystem | Rich | Medium | Medium |
CLI | Simple | Comlex | Similar to NPM |
node_modules directory | flatten | flatten | SYmlinks |