npm, yarn, pnpm, yarn-berry

ReKoding·2025년 3월 27일

JavaScript

목록 보기
6/6
post-thumbnail

JavaScript로 프로젝트를 진행해 본 경험이 있다면 패키지 매니저를 사용해 본 경험이 있을 것입니다.

그러나, 각각의 패키지 매니저의 차이를 이해하고 프로젝트에 알맞게 적용해 본 경험은 그리 많지 않을 것입니다.

오늘은 npm, yarn, pnpm, yarn berry 패키지 매니저의 특징에 대해 살펴보고, 프로젝트에 적합한 패키지 매니저를 선택할 수 있는 능력을 길러보겠습니다.


패키지 매니저

패키지 매니저는 JavaScript 라이브러리와 패키지를 쉽게 관리할 수 있도록 도움을 주는 의존성 관리 도구입니다.

패키지 매니저를 사용하면 얻는 이점은?
1. 패키지 설치 및 제거
2. 의존성 관리
3. 버전 관리
4. 스크립트 실행

패키지 매니저의 도움 없이 패키지를 사용자가 직접 관리할 수도 있지만, 그렇게 되면 복잡성, 버전 충돌, 시간적 비효율 등의 문제들을 쉽게 해결할 수 없기 때문에 주로 프로젝트에 패키지 매니저를 사용하여 관리합니다.

JavaScript의 패키지 매니저에는 크게 npm, yarn, pnpm, yarn berry가 존재합니다.

대부분의 자바스크립트 패키지 매니저는

  • node.js 실행 환경에서 돌아갑니다.
  • package.json 파일에 프로젝트가 의존하고 있는 패키지 목록을 명시합니다.
  • 일반적으로 패키지는 프로젝트의 node_modules 디렉토리에 저장됩니다.

npm

npm은 JavaScript 런타임 환경인 Node.js의 기본이 되는 패키지 매니저입니다. npm은 기본적으로 Node.js를 설치하면 자동으로 함께 설치되는 패키지 매니저이기 때문에 다른 패키지 매니저들과 다르게 별도의 설치 없이 쉽게 사용할 수 있습니다.

사용방법

  • npm install 주소 : 특정 저장소 내 패키지 설치
  • npm install 주소 -g : 로컬의 다른 프로젝트 내 패키지 설치 (글로벌 설치)
  • npm update : 설치한 패키지 버전 업데이트
  • npm dedupe : 중복 설치된 패키지를 정리

1. 일관적이지 않은 패키지 버전

Node 모듈들은 기본적으로 시멘틱 버저닝 기법을 사용하여 버전을 나타냅니다.

시맨틱 버저닝이란
1.2.3 처럼 버전을 세 가지 숫자로 구분하고 각 자리에 현재 버전이 이전 버전과 어떤 관계가 있는지 암시하는 방법입니다.


위 이미지를 보면 캐럿 기호(^)가 들어가 있는 것을 확인할 수 있습니다.

캐럿 기호란(^)
^9.17.0과 같이 첫 번째 숫자인 메이저 버전을 제외한 두 자리 (마이너, 패치) 버전까지는 변경을 허용할 수 있다는 의미입니다. 쉽게 말해, 메이저 버전 9는 변경되지 않고 두 자리는 (9.20.0, 9.31.9) 처럼 모두 사용될 수 있습니다.

npm install 명령어를 통해 모듈을 설치하면 메이저 버전 중 최신 버전을 다운로드 받게 됩니다.
빌드에 따라 유연하게 버전을 선택할 수 있다는 장점도 있지만, 사용하는 모듈간 불일치로 인해 문제가 발생할 수도 있습니다.

2. 고정되지 않은 설치 순서

npm은 모듈 이름을 사전 순서대로 정렬하여 설치하므로, 개발자의 환경에 따라 모듈의 설치 순서가 달리질 수 있습니다.
이로 인해 동일한 프로젝트에서 추가로 모듈을 설치할 경우, 초기에 설치한 사람과 설치 순서가 달라질 수 있습니다.

이러한 이유로 npm의 설치 순서가 고정되지 않아 npm의 lock 파일(package-lock.json)을 활용해 의존성의 일관성을 유지하는 것이 중요합니다.

3. 순차적인 설치로 인한 긴 소요시간

npm은 모듈들을 한 번에 하나씩 순차적으로 설치합니다. 설치해야 하는 모듈의 수가 많을수록 총 설치 시간이 길어지게 됩니다. 첫 번째 모듈의 설치 시간이 길어질 경우, 이는 전체 빌드 및 배포 시간에도 부정적인 영향을 미칠 수 있습니다. 이로 인해 개발자들은 효율적인 작업 흐름을 유지하기 어려워질 수 있습니다.


yarn

yarn은 위에서 말한 npm의 문제들을 해결하기 위해 등장했습니다.

사용방법

  • yarn add 주소 : 특정 저장소 내 패키지 설치
  • yarn global add 주소 : 로컬의 다른 프로젝트 내 패키지 설치 (글로벌 설치)
  • yarn update : 설치한 패키지 버전 업데이트
  • yarn dedupe : 중복 설치된 패키지를 정리

1. yarn.lock 파일 생성

yarn은 사용할 모듈의 버전을 yarn.lock 파일에 저장하여 관리합니다. 파일을 통해 정확한 버전을 관리하기 때문에 다른 사용자가 프로젝트를 개발할 때 항상 같은 버전의 모듈을 사용할 수 있도록 보장합니다. 덕분에 npm의 일관적이지 않은 패키지 버전 문제를 해결했습니다.

최근 npm은 많은 발전을 통해 package-lock.json 파일을 통해 모듈의 버전을 관리하여 기존 npm의 문제를 해결했습니다.

2. 설치 확인을 위한 checksum 사용

yarn은 checksum을 활용하여 패키지가 설치 되었는지 확인합니다.
yarn.lock 파일을 확인해보면 resolved 주소 뒤에 해시값이 추가 되어있는 것을 확인할 수 있습니다. 이 해시값이 바로 checksum입니다.

3. 패키지 설치 속도 (캐시, 병렬처리)

yarn은 패키지 다운로드 속도가 정말 빠릅니다. yarn은 캐시를 사용하여 한 번 다운로드 한 패키지는 그 다음부터 빠른 속도로 설치할 수 있습니다. 또한 병럴 다운로드를 지원하여 순차적으로 설치해야하는 npm과 달리 모듈을 한꺼번에 설치합니다.


yarn berry

yarn berry는 yarn v2 이상 부르는 명칭이며, 기존의 yarn v1은 yarn classic이라고 부르게 되었습니다.

yarn berry는 yarn v1의 node_modules유령 의존성 문제를 해결하기 위해 등장한 패키지 매니저입니다.

유령 의존성이란
개발을 하다 보면, 어떤 패키지는 package.json에 명시적으로 추가한 적이 없는데도 프로젝트에서 사용할 수 있는 경우가 있습니다. 또는 npm install, yarn을 했을 때 예상보다 더 많은 패키지가 설치되는 경우가 있습니다. 이런 현상을 유령 의존성이라고 부릅니다.

사용방법

npm install yarn -g
yarn set version berry

1. Plug'n'Play

Plug'n'Play는 yarn berry가 제공하는 새로운 패키지 관리 시스템입니다. 기존의 무거웠던 node_modules 대신 패키지들에 대한 정보를 zip 파일로 압축하여 .yarn/cache 폴더에 저장하고 이를 찾기 위한 정보를 .pnp.cjs 파일에 생성 후 의존성 트리 정보를 단일 파일에 저장합니다.

#!/usr/bin/env node
/* eslint-disable */
// @ts-nocheck
"use strict";

const RAW_RUNTIME_STATE =
'{\
  "__info": [\
    "This file is automatically generated. Do not touch it, or risk",\
    "your modifications being lost."\
  ],\
  "dependencyTreeRoots": [\
    {\
      "name": "rekoding-blog",\
      "reference": "workspace:."\
    }\
  ],\
  "enableTopLevelFallback": true,\
  "ignorePatternData": "(^(?:\\\\.yarn\\\\/sdks(?:\\\\/(?!\\\\.{1,2}(?:\\\\/|$))(?:(?:(?!(?:^|\\\\/)\\\\.{1,2}(?:\\\\/|$)).)*?)|$))$)",\
  "fallbackExclusionList": [\
    ["rekoding-blog", ["workspace:."]]\
  ],\

위와 같이 .pnp.cjs는 의존성 트리를 맵으로 표현하였으며, 기존 Node가 파일시스템에 접근하여 I/O를 실행하던 비효율을 자료구조를 메모리에 올리는 방식으로 탐색을 최적화한 것입니다.

별도의 I/O 작업 없이도 패키지의 정확한 위치를 알 수 있기 때문에 시간 단축과 중복 설치를 방지하며, 패키지들을 호이스팅시킬 필요가 없는 Plug'n'Play의 특성 덕분에 유령 의존성 문제도 해결할 수 있었습니다.

2. Zero Install

zero install을 사용하면 git clone 이후 별도의 설치 없이 바로 패키지들을 사용할 수 있습니다. 별도의 설치가 필요 없기 때문에 브랜치를 변경해도 해당 브랜치에 이미 필요한 의존성 패키지가 존재하므로 yarn install 없이 프로젝트 실행이 가능합니다.

이로 인해 CI에서 의존성을 설치하는 시간을 절약할 수 있게 되었습니다.


pnpm

pnpmnpmyarn의 비효율을 개선하기 위해 등장한 패키지 매니저입니다.

npm과 yarn에는 어떤 비효율이 있었을까?
npm으로 프로젝트를 관리하다보면, 여러 프로젝트에서 같은 의존성을 사용하는 경우가 있습니다.

예를 들면 React 프로젝트가 여러 개 존재할 수 있습니다.
이떄, npm이나 yarn을 사용하면 여러 개 프로젝트에서 모두 node_modules 폴더에 각각의 라이브러리를 설치해야 합니다.

결과적으로 로컬 하드 디스크에 똑같은 파일이 여러개 설치 되는 것입니다.

이러한 문제를 해결하기 위해 등장한 패키지 매니저가 pnpm입니다.

pnpmglobal 저장소에 패키지를 한 번만 저장함으로써 저장 공간을 절약할 수 있다는 아주 큰 장점을 가지고 있습니다.

사용방법

  • pnpm install : 패키지 전체 설치
  • pnpm add 주소 : 특정 저장소 내 패키지 설치
  • pnpm <script> : start, dev 등 package.json script 명령어

pnpm의 특징

  • 중앙 저장소 (Global Store) : pnpm은 모든 패키지 파일을 중앙 저장소에 저장하며, 중앙 저장소에는 각 패키지의 버전 별로 실제 파일이 저장됩니다. 중앙 저장소는 일반적으로 홈 폴더 아래에 위치하며, 모든 pnpm 프로젝트에 공유되어 동일한 패키지를 다시 설치할 필요가 없습니다.
  • 하드 링크 (Hark Links) : 하드 링크는 중앙 저장소에 실제 저장된 패키지를 가리키는 포인터로 여러 프로젝트에서 중앙 저장소에 있는 같은 파일을 참조하기 때문에 프로젝트별로 중복 설치를 방지할 수 있습니다. (중앙 저장소의 실제 파일을 가리키며, 수정 시 원본 파일이 변경됩니다.)
  • 심볼릭 링크 (Symbolic Links) : 심볼릭 링크는 중앙 저장소의 실제 패키지 파일 경로를 참조하는 포인터입니다. 프로젝트에서 중앙 저장소의 패키지에 접근할 수 있으며, 패키지가 업데이트되면 자동으로 반영됩니다.(파일의 경로를 저장하는 포인터로 원본 파일이 이동되거나 삭제되면 유효하지 않은 링크가 됩니다.)

1. 효율적인 저장 공간 관리

pnpm의 가장 큰 특징은 중복된 패키지를 저장하지 않는 방식입니다. 중앙 저장소를 사용하여 패키지 파일을 저장하고 하드 링크와 심볼릭 링크를 사용하여 중앙 저장소에 저장된 하나의 동일한 패키지를 여러 프로젝트에서 공유할 수 있기 때문에 디스크 사용량을 줄여주며, 여러 프로젝트를 동시에 진행하는 개발 환경에서 매우 유용합니다.

2. 빠른 설치 속도

pnpm은 중복된 패키지의 다운로드를 방지하며, 이미 설치된 패키지를 재 사용하며, 패키지 파일을 실제로 복사하는 대신 하드 링크를 사용하고 패키지들을 병렬 처리로 설치하는 방식이기 때문에 설치 속도를 더욱 향상시킵니다.

3. 호환성 및 편의성

pnpm은 npm 레지스트리와 호환되기 때문에 pnpm을 사용하면서도 npm을 통해 관리되는 수많은 패키지들을 자유롭게 접근하고 사용할 수 있기 때문에 pnpm으로 마이그레이션하기 쉽다는 장점이 있습니다.
또한 다양한 옵션을 제공하여 프로젝트의 요구사항에 맞게 조정할 수 있습니다.

참고

profile
코드로 기록하며 성장하는 개발자, 지식의 공유와 개발 커뮤니티에 기여하는 열정을 가지고 있습니다.

0개의 댓글