패키지 매니저란?
소프트웨어 개발 과정에서 라이브러리나 프레임워크, 모듈, 플러그인과 같은 외부 패키지의 관리는 필수적이다. 이러한 패키지를 다루는 작업을 편리하고 안전하게 수행하기 위해 사용되는 툴을 패키지 매니저라고 한다.
패키지 매니저는 패키지 설치, 업데이트, 수정, 삭제 등을 쉽게 작업할 수 있게 해준다. 예를 들어 JavaScript나 TypeScript에서 require나 import를 사용해서 외부 의존성을 참조하는데 올바르게 참조해줄 수 있도록 보장해준다.
패키지 매니저의 기본적인 기능
- 버전 관리
- 모든 dependencies 일괄 설치 또는 업데이트
dependencies 추가, 업데이트, 삭제
- 스크립트 실행
- 패키지 퍼블리쉬
- 보안 검사
등 패키지 매니저는 위와 같은 기본적인 기능을 제공한다.
대표적인 자바스크립트 프로젝트에서의 패키지 매니저에는 npm, yarn classic, yarn berry, pnpm이 있다.
npm
패키지 매니저의 시초, 플젝트의 의존성을 수동으로 다운로드해야 했던 불편함을 개선했다.
Node.js에 내장 되어 있기 때문에 추가적인 설치 필요 X
가장 널리 오랫동안 사용되어 생태계가 넓다.
npm의 단점
비효율적인 의존성 검색
node_modules 라는 폴더 아래의 파일 시스템으로 의존성을 관리하는데, 이는 비효율적이고 무거운 방법이다.
require 명령어로 react 패키지를 불러오는 상황일 때, 복잡한 구조의 폴더리스트를 순서대로 탐색하는 과정을 거친다.
탐색 비용이 많이 소모되어 node_moules의 중첩이 많은 패키지 탐색 시엔 더 많은 시간이 소요된다.
환경에 따라 달라지는 동작
npm은 패키지를 찾지 못하면 상위 디렉토리의 node_moules 폴더를 계속 검색한다.
상위 디렉토리가 어떤 node_moules를 포함하고 있는지에 따라 의존성을 불러올 수 있기도 하고 없기도 하다.
다른 버전의 의존성을 잘못 불러올 수도 있다.
비효율적인 설치
node_modules는 매우 큰 공간을 차지한다. 용량만 많이 차지할 뿐만 아니라, 큰 node_modules 구조를 만들기 위해 수많은 I/O 작업 필요하다. 속도도 느려지고 이로 인해 yarn(classic)과 npm은 의존성 트리의 유효성까지만 검증하고 각 패키지의 내용이 올바른지는 확인하지 않는다.
유령 의존성
yarn(classic)과 npm은 중복해서 설치되는 node_moules를 아끼기 위해 호이스팅 기법을 사용한다.
Dependency Tree에서 A(1.0)과 B(1.0)은 두 번 설치되기 때문에 디스크 공간을 낭비하게 된다. 이 낭비를 하지 않기 위해 오른쪽의 트리 모양처럼 바꾸게 되는데 루트 경로에서 원하는 패키지를 탐색할 수 있으므로 효율적이지만 이는 직접적으로 설치하지 않은 B 패키지를 사용할 수 있게 되었으므로 유령 의존성 문제가 발생하게 된다. 직접 의존하고 있지 않은 라이브러리에 접근할 수 있으면 추후 의존성 관리 시스템을 혼란스럽게 만들기 때문에 좋지 않다.
yarn
Facebook에서 개발한 패키지 매니저로, npm과 비슷한 목적을 가지고 있다. npm의 단점을 보완하고, 더 나은 성능과 안정성을 제공한다. npm과 프로세스가 거의 동일하지만 보안적인 면과 속도에서 큰 차이점이 있다. 여러 개의 패키지를 병렬로 설치하여 빠른 속도를 보장한다. yarn.lock 파일을 사용하여 의존성을 더욱 확실히 관리한다. 이를 통해 의존성 트리를 고정시켜 모든 기기에서 고정된 버전을 사용할 수 있도록 해준다. 또 캐시 기능을 제공하여 패키지 다운로드를 최적화한다.
yarn berry
Yarn의 새로운 버전으로, 다중 패키지 프로젝트를 위한 기능을 강화한 패키지 매니저다.
Zero-install과 PnP(Plug n Play)를 통해 의존성 설치 속도를 향상시키고 저장 공간을 절약한다.
node_modules 생성 X, .yarn 경로 하위에 의존성들을 zip 포맷으로 압축 저장 후 .pnp.cjs 파일에 의존성 트리 정보를 저장
=> 인터페이스 링커
위의 호이스팅 동작이 일어나지 않도록 nohoist 옵션이 활성화되어있다.
Workspaces 기능을 제공하여 모노레포로 프로젝트를 관리할 수 있다.
+++ Zero-Install 이란?
PnP 모드로 설치한 패키지 파일들(.yarn/cache 폴더의 파일)은 오프라인 캐시 역할도 가능하다.
이 의존성들을 git 커밋에 포함시켜 repository에 올려두면 별도의 패키지 설치 없이 git clone 이후 바로 실행할 수 있다.
새로 저장소를 복제하거나 브랜치를 바꾸었다고 해서 yarn install을 실행하지 않아도 되고 CI에서 의존성 설치하는 시간을 크게 절약할 수 있다는 장점이 있다.
pnpm
프로젝트 별로 node_modules라는 폴더에 패키지를 설치하는 방식인 npm의 의존성 문제를 해결하기 위해 고안된 패키지 매니저.
pnpm은 npm과 다르게 global 저장소에 패키지를 한 번만 저장함으로써 의존성을 공유하여 저장 공간을 절약할 수 있다.
패키지 별 설치 순서를 계산할 필요가 없어 병렬 설치를 지원하여 npm보다 빠른 설치 속도를 보여준다.
단, 프로젝트끼리 호환 문제가 발생하지 않도록 버전 관리를 해주어야 한다.
참고
https://devocean.sk.com/blog/techBoardDetail.do?ID=166592&boardType=techBlog
https://toss.tech/article/lightning-talks-package-manager
https://toss.tech/article/node-modules-and-yarn-berry