레지스트리
추가된 버전: v11.23.0
pnpm-workspace.yaml의 registries 설정은 프로젝트가 설치에 사용하는 각 레지스트리를 레지스트리 URL을 키로 하여 한 번씩 선언합니다. pnpm이 레지스트리에 대해 아는 모든 정보는 해당 항목에 담깁니다. 즉, 그 레지스트리로 라우팅되는 스코프, 그 레지스트리가 응답하는 bare specifier 접두사, 그리고 그 뒤에 있는 서버의 특성입니다.
registries:
https://npm.corp.example.com/:
serverType: artifactory
scopes: ["@acme", "@corp-tools"]
prefix: work
https://verdaccio.corp.example.com/:
scopes: ["@"]
supportsTimeField: true
항목의 모든 정보가 해당 서버에 관한 정보이기 때문에 URL이 키가 됩니다. 만약 tarball 레이아웃의 키가 스코프라면, 레이아웃은 스코프가 현재 가리키는 대상에 묶이게 되고, 스코프가 서로 다르게 해석되는 두 개발자는 어떤 URL을 생략할 수 있는지에 대해 서로 다른 lockfile을 작성하게 됩니다.
항목에는 다음 필드를 포함할 수 있습니다:
| 필드 | 유형 | 선언하는 내용 |
|---|---|---|
scopes |
string[] |
이 레지스트리로 라우팅되는 패키지 스코프입니다. |
prefix |
string |
이 레지스트리가 응답하는 bare specifier 접두사입니다. |
serverType |
string |
서버가 tarball URL을 구성하는 방식으로, npm 또는 artifactory입니다. |
supportsTimeField |
boolean |
서버의 축약 메타데이터에 time 필드가 포함되는지 여부입니다. |
그 밖의 필드는 거부됩니다. 특히 자격 증명(_authToken, _auth, _password, username, tokenHelper)과 TLS 자료(ca, cafile, cert, certfile, key, keyfile)는 조용히 무시되지 않고 거부됩니다. pnpm-workspace.yaml은 저장소에 커밋되므로 이러한 값은 .npmrc에 두어야 합니다(예: //npm.corp.example.com/:_authToken=...). 같은 이유로 user:pass@ 자격 증명이 포함된 URL 키도 거부됩니다.
패키지를 레지스트리로 라우팅하기#
scopes#
패키지가 이 레지스트리에서 해석되는 스코프로, @ 접두사를 붙입니다. 단독 "@"는 스코프가 없는 기본 레지스트리를 라우팅합니다. 이는 registry 설정이 지정하는 레지스트리와 같습니다:
registries:
https://npm.corp.example.com/:
scopes: ["@acme"]
https://registry.internal.example.com/:
scopes: ["@"]
하나의 스코프는 정확히 하나의 레지스트리로 해석되므로, 두 항목에서 같은 스코프를 라우팅하면 오류가 발생합니다.
prefix#
"lib": "work:^2.0.0"에서처럼 이 레지스트리가 응답하는 이름 있는 레지스트리 접두사입니다:
registries:
https://npm.work.example.com/:
prefix: work
pnpm add work:@corp/lib@^2.0.0
각 항목은 최대 하나의 접두사를 선언하며, 두 항목이 같은 접두사를 선언할 수 없습니다. 접두사는 lockfile 패키지 키(foo@work:1.0.0)에서 레지스트리의 식별자이므로, 두 번째 표기가 있으면 같은 레지스트리의 같은 패키지가 두 번 키로 지정되기 때문입니다.
여기서 선언한 접두사는 이 설정이 대체하는, 사용 중단된 namedRegistries 설정과 같은 규칙을 따릅니다. 내장 별칭인 gh:와 npmjs:는 자체 URL에 해당 접두사를 선언하여 재정의할 수 있고, 예약된 이름은 거부되며, 접두사를 통해 해석된 패키지는 레지스트리가 명시된 lockfile 키를 갖습니다.
서버 설명하기#
serverType#
모든 레지스트리가 npm 레지스트리와 같은 방식으로 tarball URL을 구성하는 것은 아닙니다. pnpm은 패키지의 이름, 버전, 레지스트리로부터 URL을 다시 만들 수 있으면 pnpm-lock.yaml에서 tarball URL을 생략합니다. 이 경우 lockfile에는 해당 패키지의 호스트별 URL이 포함되지 않으므로, 레지스트리의 이름을 바꾸거나 위치를 옮겨도 lockfile이 변경되지 않습니다. pnpm이 URL을 다시 만들 수 있는지는 서버에 따라 다르며, 이를 선언하는 곳이 serverType입니다. 세 가지 상태가 있습니다:
serverType |
의미 |
|---|---|
| 선언되지 않음 | 엄격 모드: tarball URL이 정확히 표준 npm 레이아웃 URL(<registry>/<name>/-/<scopeless-name>-<version>.tgz)인 경우에만 생략됩니다. registry.npmjs.org를 제외한 모든 레지스트리는 기본적으로 이 방식으로 처리됩니다. |
npm |
서버가 registry.npmjs.org처럼 동작합니다. 즉, 스코프 패키지를 인코딩되지 않은 경로뿐만 아니라 퍼센트 인코딩된 경로(/@acme%2Fwidget/...)에서도 제공합니다. 공개 레지스트리를 충실히 미러링하거나 캐싱하는 프록시가 이에 해당합니다. registry.npmjs.org 자체에는 기본으로 적용됩니다. |
artifactory |
서버가 스코프 패키지의 tarball 파일 이름에 스코프를 반복합니다: @acme/widget/-/@acme/widget-1.0.0.tgz. 반면 npm 레이아웃에서는 스코프가 제거됩니다(@acme/widget/-/widget-1.0.0.tgz). |
JFrog Artifactory 레지스트리의 경우, 이 설정에 따라 lockfile이 모든 스코프 패키지에 대해 호스트별 tarball URL을 기록하거나 하나도 기록하지 않게 됩니다:
registries:
https://acme.jfrog.example.com/artifactory/api/npm/npm-virtual/:
serverType: artifactory
scopes: ["@acme"]
일반적인 서버별 값:
| 서버 | serverType |
|---|---|
| JFrog Artifactory | artifactory |
| GitLab 패키지 레지스트리 | artifactory — 파일 이름에 스코프를 반복하는 동일한 레이아웃을 사용합니다. |
| npm 레지스트리를 충실히 미러링하거나 캐싱하는 프록시 | npm |
| Verdaccio, Sonatype Nexus, Azure Artifacts | 필요 없음 — 정확한 표준 npm 레이아웃을 제공하므로 엄격한 기본값으로도 이미 URL을 다시 만들 수 있습니다. |
| GitHub Packages | 없음 — 다운로드 URL에 패키지 식별 정보로부터 도출할 수 없는 콘텐츠 다이제스트가 포함되어 있으므로 lockfile에 유지됩니다. |
레이아웃은 추론되지 않고 반드시 선언해야 합니다. 가상 저장소는 각 패키지가 업스트림에서 동기화되었는지 로컬에서 게시되었는지에 따라 두 레이아웃을 동시에 제공할 수 있으므로, pnpm이 감지할 수 있는 레지스트리 수준의 신호가 없기 때문입니다. 또한 명시적으로 선언하면 잘못된 값이 조용한 오작동이 아니라 수정 가능한 설정 오류로 남습니다.
주의
serverType은 서버 운영자만 할 수 있는 서버에 대한 선언이며, lockfile은 이에 의존합니다. 생략된 tarball URL은 --frozen-lockfile 설치를 포함한 모든 설치에서 선언된 레이아웃을 사용해 다시 만들어집니다. 서버가 실제로 제공하는 레이아웃을 선언하세요. 선언한 후에는 lockfile에 일회성 변경이 생깁니다. pnpm이 이제 다시 만들 수 있는 URL은 lockfile을 작성하는 다음 설치 시 lockfile에서 사라집니다.
supportsTimeField#
이 레지스트리의 축약 메타데이터에 time 필드가 포함되는지 여부입니다. registry.npmjs.org의 축약 메타데이터에는 이 필드가 없습니다. 그래서 기본값이 false이며, minimumReleaseAge와 같은 시간 기반 해석 기능은 훨씬 큰 전체 메타데이터 문서를 대신 사용합니다. 이 필드를 제공하는 레지스트리 — Verdaccio v5.15.1+ 및 여러 프록시 — 는 선언해 둘 가치가 있습니다:
registries:
https://verdaccio.corp.example.com/:
scopes: ["@"]
supportsTimeField: true
이는 registrySupportsTimeField 설정의 레지스트리별 형태입니다. 대체 동작은 레지스트리별로 결정됩니다. 전체 메타데이터가 필요한 레지스트리가 하나 있더라도 다른 레지스트리에서는 더 이상 그 비용이 들지 않으며, 프로젝트가 설명하지 않은 모든 레지스트리에는 여전히 registrySupportsTimeField가 적용됩니다.
설정을 둘 수 있는 위치#
lockfile이 이 설정에 의존하므로 이 설정은 .npmrc나 전역 설정이 아닌 pnpm-workspace.yaml에 두어야 합니다. 한 개발자가 생략한 tarball URL을 다른 개발자가 다르게 재구성하면 frozen 설치가 실패하기 때문입니다.
전역 설정 파일(config.yaml)에는 라우트 — scopes와 prefix — 를 선언하여 스코프나 work: 같은 별칭이 머신의 모든 프로젝트에 적용되도록 할 수 있습니다. 위와 같은 이유로 서버 설명(serverType 및 supportsTimeField)은 pnpm-workspace.yaml에서만 읽습니다.
라우트를 선언하지 않은 항목은 다른 곳에서 설정된 레지스트리를 설명합니다. 예를 들어 .npmrc에 설정된 기본 레지스트리가 있습니다. 이러한 항목은 해당 URL이 프로젝트가 실제로 해석에 사용하는 레지스트리일 때만 적용됩니다. 설정된 어떤 레지스트리와도 일치하지 않는 항목은 아무 효과 없이 남아 있게 되므로 pnpm이 경고합니다(오래된 URL, 이동된 스코프).
이 설정의 URL 키에서는 환경 변수가 확장되지 않습니다. 이는 다른 pnpm-workspace.yaml의 레지스트리 URL에서 확장되지 않는 것과 같은 이유입니다. 이 파일은 커밋되며, 환경 변수를 요청 대상으로 확장하면 공격자가 제어하는 호스트로 비밀 정보가 유출될 수 있습니다. ${...} 자리 표시자가 포함된 키는 무시됩니다.
이전 형식#
v11.23.0 이전에는 registries가 스코프를 URL에 매핑했으며, default 키로 기본 레지스트리를 지정했습니다:
registries:
default: https://registry.npmjs.org/
"@acme": https://npm.corp.example.com/
이 형식은 여전히 허용되며 이전과 같이 동작합니다. 두 형식을 하나의 맵에 섞어 쓸 수는 없습니다. 값이 문자열인 항목은 스코프 라우트이며, URL을 키로 하는 스코프 라우트는 오류입니다.
namedRegistries 설정은 사용 중단되었으며 prefix로 대체되었습니다. 이 설정은 여전히 읽히지만 registries가 선언하지 않은 접두사에 대해서만 적용되며, 둘 다 접두사를 선언하면 pnpm이 경고합니다.