paint-brush
PNPM과 YARN이 필요하지 않은 이유by@bormando

PNPM과 YARN이 필요하지 않은 이유

Dmitrii Bormotov9m2024/07/23
Read on Terminal Reader

npm은 **Node.js** 생태계의 기본 패키지 관리자입니다. 설치 패키지와 함께 제공되므로 컴퓨터에 **Node.js**를 설치할 때(또는 **Node.js**를 설정한 경우 모든 **CI** 제공자에) 기본적으로 사용할 준비가 되어 있습니다. 안정적이고 속도도 다른 패키지 관리자와 비슷합니다.
featured image - PNPM과 YARN이 필요하지 않은 이유
Dmitrii Bormotov HackerNoon profile picture
0-item

여러분, 안녕하세요!


다양한 패키지 관리자를 사용하는 Node.js 프로젝트를 본 적이 있을 것입니다. 예:



나는 그것을 보고 위의 모든 작업을 수행했지만 항상 마음 속에 질문이 있었습니다. 사람들/팀이 npm 대신 Yan 또는 pnpm을 사용하도록 유도하는 이유는 무엇입니까? 장점은 무엇입니까? 단점이 있나요?


음… 알아봅시다!

성능 비교 규칙

나는 "속도" 측면에서 npm , Yarnpnpm을 비교하기로 결정했습니다…


아래에 3가지 측정값이 표시됩니다.


  1. 캐시 없이 잠금 파일을 생성합니다.


  2. 캐시 없이 기존 잠금 파일에서 종속성을 설치합니다.


  3. 글로벌 캐시를 사용하여 기존 잠금 파일의 종속성을 설치합니다.


캐시에는 두 가지 유형이 있습니다.


  1. 글로벌.

    일반적으로 사용자의 홈 디렉터리(fe, ~/.yarn/berry/cache )에 저장됩니다.


  2. 현지의.

    프로젝트 디렉터리(fe, <project-dir>/.yarn )에 저장됩니다.


내 경험상 #2#3이 가장 일반적인 사용 사례이지만, 만일을 대비해 #1도 사용했습니다(매우 드문 경우임에도 불구하고).


벤치마크의 예로 create-react-app 의 샘플 프로젝트를 사용했습니다.

npm

Node.js 생태계의 기본 패키지 관리자입니다. 달리 무슨 말을 해야 할까요? 설치 패키지와 함께 제공되므로 컴퓨터에 Node.js를 설치할 때(또는 Node.js를 설정한 경우 CI 공급자에) 기본적으로 사용할 준비가 되어 있습니다.


제 생각에는 엄청난 "프로"입니다. 별도로 설치할 필요가 없습니다!


거기에는 뛰어난 것이 없습니다. 단지... 작동합니다! 그리고 지난 몇 년 동안 큰 버그를 본 적이 없습니다. 상당히 안정적이고 작업이 완료되는 것 같습니다.


지금까지 사용한 npm 의 기능은 다음과 같습니다.


  1. 종속성 관리(설치, 제거, 업데이트)
  2. 패키지 게시(비공개, 공개)
  3. 링크-로컬 패키지
  4. 작업공간을 관리하세요.

종속성 관리

npm은 프로젝트 루트의 node_modules 폴더에 종속성을 저장합니다. 꽤 직설적 인.


ℹ️ package-lock.json 나열된 패키지의 레지스트리에 대한 정보를 저장합니다. 단일 범위(예: @example-company 의 패키지가 다른 레지스트리(예: npm & GitHub 패키지 )에 있는 경우 매우 유용합니다.


package-lock.json 항목


이제 설치 속도 측면에서 어떤 성능을 발휘하는지 살펴보겠습니다.

캐시 없이 package-lock.json 생성

package-lock.json을 생성하고 캐시 없이 종속 항목을 설치합니다.


걸렸다 1 분 npm 에서 package-lock.json 생성하고 캐시 없이 종속성을 설치합니다.


사용된 명령:

 npm i

캐시 없이 package-lock.json에서 종속성 설치

캐시 없이 package-lock.json에서 종속 항목 설치


걸렸다 18초 캐시 없이 package-lock.json 의 종속성을 설치하려면 npm을 사용하세요.


사용된 명령:

 npm ci

글로벌 캐시를 사용하여 package-lock.json에서 종속성 설치

전역 캐시를 사용하여 package-lock.json에서 종속 항목 설치


걸렸다 8초 npm 에서 전역 캐시를 사용하여 package-lock.json 의 종속성을 설치합니다.


사용된 명령:

 npm ci

작업공간 관리

작업공간을 생성하고 전체 작업공간에 대한 종속성을 한 번에 관리할 수 있었고, 특정 프로젝트에 대해서는 별도로 종속성을 관리할 수 있었습니다.


즉, 버그/문제 없이 작업을 완료하며 공식 문서는 매우 간단합니다.


지금까지 사용한 Workspace 기능:


  1. 작업공간 내의 모든 프로젝트에 대한 종속성을 설치합니다.
  2. 단일 특정 프로젝트에 대한 종속성을 설치합니다.
  3. 모든 프로젝트에 대해 단일 스크립트를 한 번에 반복적으로 실행합니다.

솔직히 저는 기능 중 일부를 많이 시도하지 않았습니다. 내 말은, 일부 프로젝트에서 작업하는 동안 "종속성 설치"라는 측면에서 이를 많이 사용했다는 것입니다.


Yarn은 Node.js 설치 프로그램과 함께 제공되지 않으므로 별도로 설치해야 합니다. 이는 CI 파이프라인에 추가 단계가 있다는 것을 의미합니다. 즉, 프로젝트 종속성을 설치하기 전에 Yarn을 설정해야 합니다.

종속성 관리

Yarn에는 종속성을 설치하는 두 가지 접근 방식이 있습니다.


  1. " Zero Installs "(기본값) - .yarn 폴더를 생성하고 yarn.lock.pnp.cjs 파일에 패키지를 나열합니다.


  2. npm 과 유사한 일반 모듈은 종속성을 node_modules 에 저장하고 이를 yarn.lock 파일에 나열합니다.


ℹ️ 원사 잠금 파일은 이전(일반) 설치 접근 방식을 사용하는 경우 에만 나열된 모든 패키지의 레지스트리에 대한 정보를 저장합니다.


⚠️ " Zero Installs "는 패키지를 로컬 캐시에 저장하고 잠금 파일에 대한 링크를 제공하는 것처럼 보입니다.


패키지 링크

하나의 정리된 환경에 종속성을 설치한 다음 이를 다른 환경으로 이동하려는 Dockerfile 또는 CI 파이프라인이 있는 경우 중요할 수 있습니다( .yarn 폴더와 로컬 캐시를 모두 복사해야 함).


이제 Yarn의 기본 접근 방식은 " Zero Installs "이고 이전 접근 방식보다 더 나은 성능을 제공하므로 이 접근 방식에 대해서만 벤치마크를 기록하겠습니다.

캐시 없이 잠금 파일 생성

Yarn을 사용하여 잠금 파일을 생성하고 종속성을 설치합니다.


걸렸다 16.5초 Yarnyarn.lock 파일을 생성하고 캐시 없이 종속성을 설치합니다.


사용된 명령:

 yarn install

캐시 없이 기존 잠금 파일에서 종속성 설치

캐시 없이 "Zero Install" 접근 방식으로 종속성 설치


걸렸다 11초 Yarn이 "Zero Install" 접근 방식을 사용하고 캐시 없이 종속성을 설치하려면


사용된 명령:

 yarn install --frozen-lockfile

글로벌 캐시를 사용하여 기존 잠금 파일에서 종속성 설치


"Zero Install" 접근 방식 및 글로벌 캐시를 사용하여 종속성 설치


걸렸다 8초 Yarn이 "Zero Install" 접근 방식과 글로벌 캐시를 사용하여 종속성을 설치하도록 합니다.


사용된 명령:

 yarn install --frozen-lockfile

작업공간 관리

작업공간을 생성하고 모든 프로젝트에 대한 종속성을 한 번에 관리할 수 있었고, 특정 프로젝트에 대해서는 별도로 종속성을 관리할 수 있었습니다.


지금까지 사용한 Workspace 기능:


  1. 작업공간 내의 모든 프로젝트에 대한 종속성을 설치합니다.
  2. 단일 특정 프로젝트에 대한 종속성을 설치합니다.
  3. 모든 프로젝트에 대해 단일 스크립트를 한 번에 반복적으로 실행합니다.


문서는 훌륭하지만 명령 이름과 플래그가 다소 혼란스럽습니다.


예를 들어 루트 ( . ) 및 중첩된 b2b 프로젝트에서 test 스크립트를 실행하려면 다음을 실행해야 합니다.


 yarn workspaces foreach -A --include '{.,b2b}' run test


npm 과 비교하면 다음과 같습니다.


 npm run test --workspace=b2b --include-workspace-root

pnpm

pnpm은 현재 많은 회사와 오픈 소스 프로젝트에서 사용하고 있습니다 .


Yarn 과 마찬가지로 pnpm에는 Node.js 설치 프로그램이 함께 제공되지 않으므로 별도로 설치해야 합니다. 이는 CI 파이프라인에 추가 단계가 있다는 의미입니다. 프로젝트 종속성을 설치하기 전에 pnpm을 설정해야 합니다.

종속성 관리

pnpm은 " 빠르고 디스크 공간 효율적인 패키지 관리자 " 로 간주됩니다.


실제로 저는 종속성을 로컬로 관리한다는 측면에서 "디스크 공간 효율적"이라는 말에 동의합니다.


기본적으로 pnpm은 공유 종속성을 중복 제거합니다. pnpm은 여러 종속성에 사용되는 패키지에 대한 심볼릭 링크를 만듭니다. 즉, 패키지 ab 패키지 c 종속성으로 사용하는 경우 pnpm 은 패키지 c 단일 복사본으로 저장하고 패키지 ab 에 대한 심볼릭 링크를 생성합니다. 이렇게 하면 패키지 관리자가 하드 카피를 생성하지 않고 SSD/HDD에 메모리를 절약합니다.


ℹ️ pnpm-lock.yaml 나열된 패키지의 레지스트리에 대한 정보를 저장하지 않습니다.


⚠️ pnpm은 때때로 종속성을 프로젝트로 유지하는 대신 전역 캐시에 저장한다는 점을 명심하세요.

캐시 없이 pnpm-lock.yaml 생성

pnpm-lock.yaml 생성


걸렸다 31초 pnpm이 pnpm-lock.yaml 생성하고 캐시 없이 종속성을 설치하려면


사용된 명령:

 pnpm install

글로벌 캐시 없이 pnpm-lock.yaml에서 종속성 설치

글로벌 캐시 없이 pnpm-lock.yaml에서 종속성 설치


걸렸다 16초 pnpm이 캐시 없이 pnpm-lock.yaml 의 종속성을 설치하려면


사용된 명령:

 pnpm i --frozen-lockfile


글로벌 캐시를 사용하여 기존 잠금 파일에서 종속성 설치

캐시를 사용하여 pnpm-lock-yaml에서 종속성 설치


걸렸다 5 초 pnpm이 글로벌 캐시를 사용하여 pnpm-lock.yaml 의 종속성을 설치하려면


사용된 명령:

 pnpm i --frozen-lockfile

작업공간 관리

이제 상황이 정말 흥미로워집니다…


pnpm 에는 많은 구성 옵션이 있지만 일부 핵심 기능은 작동하지 않습니다!


제가 직면한 몇 가지 버그를 검토해 보겠습니다.

pnpm 설치 --필터

특정 프로젝트에 대해서만 종속성을 설치할 수 있다는 것이 중요합니다. 이는 작업 영역 내에서 특정 프로젝트와 관련된 파이프라인을 생성할 때 단일 저장소에 매우 유용합니다.


즉, 작업 공간에 다음이 있다고 상상해 보세요.


  • 웹 앱,
  • 백엔드 서버,
  • 테스트 프로젝트(종단 간 테스트).


이들 모두는 별도의 npm 프로젝트이지만 동일한 저장소의 일부입니다 ☝️


이제 파이프라인에서 엔드투엔드 테스트만 실행하기를 원합니다. 따라서 엔드투엔드 테스트 종속성만 필요합니다. 그렇죠?


글쎄, 당신은 그렇게 할 수 없을 것입니다. pnpm은 전체 작업 공간에 대한 종속성을 설치하도록 강요합니다!


pnpm install --filter <project-name> 선택한 프로젝트에 대해서만 종속성을 설치해야 했지만 작동하지 않습니다.


1년 된 버그가 있는데 최근 작동하지 않는 수정으로 종료되었습니다.

재귀 설치=false

pnpm install 실행하면 기본적으로 pnpm은 전체 작업 공간(모든 프로젝트)에 대한 종속성을 설치합니다.


작업공간 루트의 .npmrc 에서 recursive-install=false 설정하면 이 동작을 대체할 수 있습니다.


하지만 이미 거의 2년이 된 또 다른 버그가 발생했습니다 .

공유 작업공간-잠금 파일=false

pnpm은 기본적으로 종속성 목록을 단일 잠금 파일에 저장합니다( npmYarn 과 동일).


작업공간 루트의 .npmrc 에서 shared-workspace-lockfile=false 설정한 경우에도 이 동작을 대체할 수 있습니다.


그러면 작업 공간 기능을 유지하고 --ignore-workspace 플래그를 사용하여 특정 프로젝트에 대한 종속성을 설치할 수 있습니다.


어쨌든 이 설정에는 몇 가지 문제가 더 발생합니다.


  1. eslinttsc --noEmit GitHub Actions 파이프라인에서 "JavaScript Heap Out of Memory" 오류를 발생시킵니다.


  2. 일부 종속성은 전역 캐시에 저장되고 node_modules/.pnpm 에 심볼릭 링크됩니다.

성능 비교 결과

#

npm

pnpm

잠금 파일 생성

60초

16.5초

31초

캐시 없이 종속성 설치

18초

11초

8초

글로벌 캐시를 사용하여 종속성 설치

8초

8초

5초


위 벤치마크에 따르면 npm은 가장 느린 패키지 관리자입니다 ☝️


어쨌든, 이 결과를 해석해 봅시다…

잠금 파일 생성

드문 경우입니다. 일반적으로 잠금 파일은 프로젝트 초기화 시 생성된 다음 패키지를 설치/업데이트할 때 확장됩니다.


이를 염두에 두고 패키지 관리자를 선택할 때 의존하는 것은 그다지 중요한 것 같지 않습니다.

종속성 설치

대부분의 경우 프로젝트는 특정 종속성 목록을 유지하며 항목을 추가/제거하는 경우는 거의 없습니다.


아마도 때때로 패키지 버전을 변경하게 될 것입니다. 이러한 변경 사항은 작으며 캐시의 나머지 패키지를 재사용하게 됩니다.


즉, 일반적인 사용 사례는 패키지 레지스트리에서 새 패키지를 가져오고 나머지는 캐시에서 가져오는 것입니다.


pnpm (5-8초)은 중간에 원사 (8-11초)가 있는 npm (8-18초)보다 거의 두 배 빠릅니다.

결론

사리

  • pnpm은 실제로 "빠르고 디스크 효율적인" 패키지 관리자입니다. 현재 리뷰에서는 매우 명확합니다!


  • pnpm 작업 공간 기능에 버그가 있으며 일부 버그는 수년 동안 해결되지 않았습니다.


  • pnpmYarn 모두 CI 파이프라인에 추가 설정이 필요하지만 npm은 그렇지 않습니다.


  • pnpmYarn은 모두 잠금 파일에 패키지 레지스트리 정보를 저장하지 않지만 npm은 저장합니다.

저자의 생각

패키지 관리자에 대한 요구 사항이 "종속성만 설치"만큼 간단하다면 pnpm이 가장 잘 작동한다고 생각합니다.


pnpm에는 기본적으로 Node.js 설치 프로그램이 제공되지 않지만 corepack 또는 기존 작업을 사용하여 CI 파이프라인에서 쉽게 설정할 수 있습니다.


나는 다음과 같은 이유로 npm 을 선호합니다:


  • 안정적입니다(특히 작업 공간).


  • Node.js 와 함께 제공되며 CI 파이프라인에 추가 설정이 필요하지 않습니다.


  • package-lock.json 에 패키지 레지스트리를 저장하므로 다른 레지스트리의 단일 범위로 종속성을 설치할 수 있습니다.


이러한 장점은 내가 Yan 또는 pnpm 으로 절약하는 속도와 디스크 공간보다 더 중요합니다.


패키지 관리자를 선택하는 기준은 무엇입니까? 부끄러워하지 말고 아래 댓글 섹션에서 여러분의 생각을 알려주세요! 👇😊