새로운 pnpm 12에서 달라진 점
pnpm 12는 pnpm을 Rust로 다시 작성한 것으로, 현재 릴리스 후보 단계입니다. 업그레이드는 마이그레이션을 의미하지 않습니다. 아래의 차이점을 제외하면 pnpm 11의 명령, 플래그, 설정, lockfile 형식을 그대로 유지하며, 문서는 두 버전 모두에 적용됩니다.
다섯 가지가 다르며, 그중 하나인 제거된 플래그는 다르게 동작하는 것이 아니라 아예 실패합니다. 이 글에서는 이를 한곳에 모았습니다.
프로젝트 인식 전역 바이너리#
이제 전역으로 설치된 node, deno 또는 bun은 항상 전역 설치 버전을 실행하는 대신 현재 프로젝트가 고정한 버전을 따릅니다.
프로젝트가 devEngines.runtime을 통해, 또는 런타임을 종속성으로 설치하여 런타임을 고정하면, 해당 프로젝트 안에서 node를 실행할 때는 고정된 버전이 사용되고, 어떤 프로젝트에도 속하지 않은 곳에서 실행할 때는 전역 버전이 사용됩니다. 이러한 동작을 위해 더 이상 별도의 버전 관리자가 필요하지 않습니다.
이를 제어하는 설정은 globalShims이며, 전체 설명은 프로젝트 인식 전역 bin에 있습니다.
Git 종속성 해석#
이제 GitHub, GitLab, Bitbucket의 저장소에서 지정자는 전송 방식의 선택이 아니라 식별자입니다. 다음은 모두 같은 종속성을 가리키며 동일하게 해석됩니다:
kevva/is-positive
github:kevva/is-positive
git+https://github.com/kevva/is-positive.git
git+ssh://git@github.com/kevva/is-positive.git
각각은 호스트의 정규 HTTPS URL을 통해 해석되며, pnpm은 이러한 호스트에 대해 SSH URL을 기록하지 않습니다. 특정 머신이 호스트에 접근할 때 어떤 전송 방식을 사용하는지는 프로젝트의 속성이 아니라 해당 머신의 Git 구성입니다. 따라서 SSH 키가 있는 노트북에서 작성한 lockfile도 SSH 키가 없는 CI 러너에서 설치됩니다.
이전 pnpm 11에서는 해석기가 전송 방식을 탐색하여 git@github.com:owner/repo.git을 기록할 수 있었고, 이 경우 해당 호스트의 키가 없는 머신을 사용하는 모든 사람에게서 실패했습니다. 이전 pnpm이 작성한 lockfile에 이러한 항목이 있다면 pnpm update <package>로 해당 종속성을 한 번 다시 해석하세요. lockfile은 무엇을 설치할지에 대한 기록이므로 pnpm이 스스로 항목을 다시 작성하지는 않습니다.
SSH를 통해 비공개 저장소에 접근하려면 지정자가 아닌 Git에서 URL 재작성을 구성하세요:
git config --global url."git@github.com:".insteadOf https://github.com/
pnpm은 git을 직접 호출하므로, 재작성 설정이 모든 Git 작업에 자동으로 적용됩니다. 알 수 없는 호스트와 자격 증명이 포함된 URL을 처리하는 방법을 비롯한 자세한 내용은 Git 종속성 해석 방식에 있습니다.
패키지 관리자 지정#
버전 v12.0.0-rc.6부터 pnpm은 다른 패키지 관리자인 npm, Yarn Classic, Yarn Berry, Yarn 6(yarnpkg/zpm), Bun도 설치합니다. 따라서 이들 중 하나를 지정하면 이름이 같은 npm 패키지가 아니라 도구 자체를 의미합니다.
그 이유는 해당 npm 패키지가 도구 자체가 아니기 때문입니다. npm의 yarn은 Classic에서 멈춰 있고, Yarn 4는 @yarnpkg/cli-dist로 게시되며, Yarn 6은 npm에 아예 없고, npm의 node / deno는 빌드를 다운로드하는 래퍼입니다. 그래서 이전에는 pnx yarn@4 install이 버전 누락으로 실패했고, pnpm add -g yarn을 실행하면 Yarn 1이 설치되었습니다.
| pnpm 11 | pnpm 12 | |
|---|---|---|
pnpm add yarn | npm 패키지 yarn을 설치합니다 | 프로젝트의 패키지 관리자를 packageManager / devEngines.packageManager에 기록합니다 |
pnpm add -g yarn | 설치 대상: Yarn Classic | 현재 Yarn 계열을 설치합니다 |
pnpm add -g node / pnpm add -g deno | 래퍼 패키지를 설치합니다 | 해당 Node.js 또는 Deno 릴리스를 설치합니다 |
pnx node@22 / pnx deno | 래퍼 패키지를 실행합니다 | 해당 릴리스를 실행합니다 |
| 전역으로 설치된 패키지 관리자 | 항상 전역 사본 | 프로젝트에 고정된 버전이 있으면 이를 따릅니다 |
릴리스된 버전을 요청하는 대신 패키지의 위치를 지정하는 지정자는 여전히 지정한 대상을 설치합니다 — pnpm add yarn@npm:yarn@1.22.22, pnx yarn@yarnpkg/berry.
이로부터 두 가지가 더 이어집니다. Git에 호스팅된 종속성은 그 종속성이 요청하는 패키지 관리자로 준비되므로, Yarn으로 빌드되는 저장소도 pnpm만 있는 머신에서 설치됩니다. 그리고 pnpm shim add yarn은 현재 프로젝트가 고정한 버전을 실행하는 yarn 명령을 링크합니다. shim은 PATH의 나머지 부분을 가리기 때문에 pnpm setup이나 설치의 부수 효과로 생성되지 않습니다.
전체 설명은 기타 패키지 관리자에 있습니다.
순환 종속성 그래프의 lockfile#
버전 v12.0.0-rc.5부터 pnpm은 설치 과정에서 우연히 마주치는 위치가 아니라 고정된 위치에서 종속성 순환을 끊습니다. 순환에 속한 패키지는 패키지 ID 순으로 정렬되며, 순환을 닫는 간선은 항상 같은 지점에서 잘립니다.
그 결과 lockfile은 오직 종속성 그래프에 의해서만 결정됩니다. 이제 pnpm-workspace.yaml의 packages glob 순서를 바꾸거나, package.json의 항목 순서를 바꾸거나, 단순히 두 번 설치해도 모두 바이트 단위로 동일한 lockfile이 생성됩니다 — pnpm 11에서는 순환 종속성이 있는 프로젝트에서 서로 다른 lockfile이 생성될 수 있었습니다. 순환이 많은 워크스페이스는 피어를 2–3× 더 빠르게 해석하고, 메모리를 약 25% 덜 사용하며, lockfile도 크게 작아집니다. 순환 안의 패키지가 더 이상 자신에게 도달하는 경로마다 별도의 피어 변형을 갖지 않기 때문입니다.
기존 lockfile은 계속 동작합니다. --frozen-lockfile 설치는 이를 변경 없이 사용하며, 다시 해석하지 않는 설치는 이를 건드리지 않습니다. 다시 해석하는 첫 번째 설치에서 순환 패키지의 피어 변형 키가 한 번 다시 지정되므로, 이러한 프로젝트에서는 일회성 lockfile diff가 생길 것으로 예상하세요. 자세한 내용은 피어 해석 방식에 있습니다.
pnpm install --resolution-only가 제거됨#
pnpm 12는 이 플래그를 구현하지 않으며 이를 거부합니다:
error: unexpected argument '--resolution-only' found
이 플래그는 피어 종속성 문제를 출력하기 위해 존재했습니다. pnpm peers check는 이를 직접 수행합니다 — lockfile에서 문제를 읽기 때문에 재해석도 설치도 필요하지 않습니다:
pnpm peers check
만약 CI 스크립트에서 --resolution-only를 호출한다면, 이는 결과를 바꾸는 대신 빌드를 중단시키는 유일한 변경 사항이므로 전환하기 전에 grep으로 찾아볼 가치가 있습니다.
사용해 보기#
pnpm 12는 npm에서 next-12 태그로, GitHub에서는 프리릴리스로 게시되어 있습니다. 아직 Homebrew, winget, Scoop, Chocolatey에서는 제공하지 않습니다. 설치 방법은 pnpm 12 RC 설치를 참조하세요.
발생하는 문제가 있다면 문제를 보고해 주세요.