package.json

패키지의 매니페스트 파일입니다. 여기에는 의존성, 제목, 작성자 등을 포함한 모든 패키지의 메타데이터가 포함됩니다. 이는 pnpm을 포함한 모든 주요 Node.js 패키지 관리자에서 유지되는 표준입니다.

기존 package.json 형식 외에도 pnpm은 package.json5(json5 사용) 및 package.yaml(js-yaml 사용)도 지원합니다.

If a directory contains more than one of these files, pnpm uses package.json, then package.json5, then package.yaml. Since v11.28.0, workspace discovery follows the same order and finds one project per directory.

참고

버전 v11부터 pnpm은 더 이상 package.json의 pnpm 필드에서 설정을 읽지 않습니다. 대신 설정은 pnpm-workspace.yaml에 정의해야 합니다. 구성하기를 참조하세요.

bin#

The bin field maps command names to files inside the package. pnpm normalizes backslash separators to / and parent directory segments at the package root. For example, ../dist/cli.js resolves to dist/cli.js inside the package.

engines#

소프트웨어가 작동하는 Node 및 pnpm의 버전을 지정할 수 있습니다.

package.json
{
    "engines": {
        "node": ">=10",
        "pnpm": ">=3"
    }
}

로컬 개발 중에 pnpm의 버전이 engines 필드에 지정된 버전과 일치하지 않으면 pnpm은 항상 오류 메시지와 함께 실패합니다.

사용자가 engineStrict 구성 플래그를 설정하지 않은 경우(settings 참조), 이 필드는 권고 사항일 뿐이며 패키지가 종속성으로 설치될 때 경고만 표시합니다.

engines.runtime#

버전 10.21.0에서 추가됨

종속성에 필요한 Node.js 런타임을 지정합니다. 선언되면 pnpm은 지정된 Node.js 버전을 자동으로 설치합니다.

package.json
{
  "engines": {
    "runtime": {
      "name": "node",
      "version": "^24.11.0",
      "onFail": "download"
    }
  }
}

패키지가 런타임을 선언하면:

  1. CLI 앱의 경우: pnpm은 CLI를 필요한 Node.js 버전에 바인딩하여, 전역으로 설치된 Node.js 인스턴스와 관계없이 올바른 런타임을 사용하도록 합니다.
  2. postinstall 스크립트가 있는 패키지의 경우: 스크립트는 지정된 Node.js 버전을 사용하여 실행됩니다.

이는 올바르게 작동하기 위해 특정 Node.js 버전이 필요한 종속성에 특히 유용합니다.

devEngines.runtime#

추가된 버전: v10.14

프로젝트에서 사용하는 하나 이상의 JavaScript 런타임 엔진을 지정할 수 있습니다. 지원되는 런타임은 Node.js, Deno, Bun입니다.

예를 들어, 다음과 같이 종속성에 node@^24.4.0을 추가할 수 있습니다:

package.json
{
  "devEngines": {
    "runtime": {
      "name": "node",
      "version": "^24.4.0",
      "onFail": "download"
    }
  }
}

같은 package.json에 여러 런타임을 추가할 수도 있습니다:

package.json
{
  "devEngines": {
    "runtime": [
      {
        "name": "node",
        "version": "^24.4.0",
        "onFail": "download"
      },
      {
        "name": "deno",
        "version": "^2.4.3",
        "onFail": "download"
      }
    ]
  }
}

작동 방식:

  1. pnpm install은 지정한 범위를 일치하는 최신 런타임 버전으로 해석합니다.
  2. 정확한 버전(및 체크섬)은 lockfile에 저장됩니다.
  3. 스크립트는 로컬 런타임을 사용하므로 환경 간 일관성이 보장됩니다.

매니페스트를 수정하지 않고 선언된 onFail 동작을 재정의하려면 runtimeOnFail 설정을 사용하세요.

devEngines.packageManager#

추가된 버전: v11.0.0

package.json의 devEngines.packageManager를 통해 pnpm 버전을 지정할 수 있습니다. packageManager 필드와 달리 버전 범위를 지원합니다. 해석된 버전은 pnpm-lock.yaml의 packageManagerDependencies 아래에 저장되며, 여전히 범위를 충족하는 경우 재사용됩니다.

When the lockfile records no version yet, pnpm records the running pnpm if it satisfies the range and was published at least minimumReleaseAge ago. Otherwise pnpm records the newest version in the range that is old enough. If no version in the range is old enough, pnpm records the running pnpm.

package.json
{
  "devEngines": {
    "packageManager": {
      "name": "pnpm",
      "version": ">=11.0.0 <12.0.0",
      "onFail": "download"
    }
  }
}

참고

When pnpm is declared via the legacy packageManager field (not devEngines.packageManager), its resolution info is not written to pnpm-lock.yaml. Use devEngines.packageManager when the resolved version should be recorded in the lockfile.

매니페스트를 수정하지 않고 onFail 동작을 재정의하려면 pmOnFail 설정을 참조하세요.

dependenciesMeta#

dependencies, optionalDependencies 및 devDependencies에 선언된 종속성에 사용되는 추가 메타 정보입니다.

dependenciesMeta.*.injected#

로컬 워크스페이스 패키지인 종속성에 대해 이 값을 true로 설정하면, 해당 패키지는 가상 스토어(node_modules/.pnpm)에 하드 링크된 복사본을 생성하는 방식으로 설치됩니다.

이 값을 false로 설정하거나 설정하지 않으면, 대신 워크스페이스에 있는 패키지의 소스 디렉터리를 가리키는 node_modules 심볼릭 링크를 생성하는 방식으로 종속성이 설치됩니다. 이 방식이 더 빠르고 종속성의 변경 사항이 사용하는 쪽에 즉시 반영되므로 기본값입니다.

예를 들어, 다음 package.json이 로컬 워크스페이스 패키지라고 가정해 보겠습니다:

package.json
{
  "name": "card",
  "dependencies": {
    "button": "workspace:1.0.0"
  }
}

button 종속성은 일반적으로 card의 node_modules 디렉터리에 button의 개발 디렉터리를 가리키는 심볼릭 링크를 생성하는 방식으로 설치됩니다.

그런데 button이 peerDependencies에 react를 지정하면 어떻게 될까요? 모노레포의 모든 프로젝트가 동일한 버전의 react를 사용한다면 문제가 없습니다. 그런데 react@16을 사용하는 card와 react@17을 사용하는 form이 모두 button을 필요로 한다면 어떻게 될까요? 일반적으로는 react의 단일 버전을 선택하고 button의 devDependencies를 사용하여 지정해야 합니다. 심볼릭 링크는 card와 form 같은 서로 다른 소비자가 react 피어 종속성을 서로 다르게 충족할 수 있는 방법을 제공하지 않습니다.

injected 필드는 가상 스토어에 button의 하드 링크된 복사본을 설치하여 이 문제를 해결합니다. 이를 위해 card의 package.json을 다음과 같이 구성할 수 있습니다:

package.json
{
  "name": "card",
  "dependencies": {
    "button": "workspace:1.0.0",
    "react": "16"
  },
  "dependenciesMeta": {
    "button": {
      "injected": true
    }
  }
}

반면 form의 package.json은 다음과 같이 구성할 수 있습니다:

package.json
{
  "name": "form",
  "dependencies": {
    "button": "workspace:1.0.0",
    "react": "17"
  },
  "dependenciesMeta": {
    "button": {
      "injected": true
    }
  }
}

이러한 변경으로 button은 card와 form의 "주입된 종속성"이 됩니다. button이 react를 가져올 때, card의 컨텍스트에서는 react@16으로 해석되고 form의 컨텍스트에서는 react@17으로 해석됩니다.

주입된 종속성은 워크스페이스 소스 디렉터리의 복사본을 만들기 때문에, 코드가 수정될 때마다 이 복사본을 어떤 방식으로든 업데이트해야 합니다. 그렇지 않으면 새로운 상태가 사용하는 쪽에 반영되지 않습니다. pnpm --recursive run build와 같은 명령으로 여러 프로젝트를 빌드할 때, 이 업데이트는 각 주입된 패키지가 다시 빌드된 후, 그리고 해당 소비자가 다시 빌드되기 전에 이루어져야 합니다. 간단한 경우에는 pnpm install을 다시 실행하여 수행할 수 있으며, 해당 프로젝트 하나를 다시 빌드하기 위해 "prepare": "pnpm run build"와 같은 package.json 라이프사이클 스크립트를 사용할 수도 있습니다. Third party tools such as pnpm-sync and pnpm-sync-dependencies-meta-injected provide a more efficient solution for updating injected dependencies, as well as watch mode support.

peerDependencies#

피어 종속성 값은 일반적으로 semver 범위(^1.0.0) 또는 workspace:나 catalog: 지정자입니다.

버전 v11.14.0부터는 스킴이 포함된 지정자로도 피어 종속성을 선언할 수 있습니다:

package.json
{
  "peerDependencies": {
    "lib-a": "work:5.x.x",
    "lib-b": "npm:other-lib@^5",
    "lib-c": "file:../lib-c",
    "lib-d": "git+https://example.com/lib-d.git"
  }
}

허용되는 형식은 named-registry 사양(<registry>:<version>), npm: 별칭, 그리고 file:, git 또는 URL 사양입니다.

Such a specifier is matched against the semver range it carries: work:5.x.x is checked as 5.x.x and npm:other-lib@^5 as ^5. file:../lib-c와 같이 버전이 없는 지정자는 *와 비교되므로 어떤 버전이든 이를 충족합니다. 한편 autoInstallPeers가 누락된 피어를 설치할 때는 원래 지정자가 패키지를 선택하므로, 피어는 지정한 별칭 이름, 레지스트리 또는 소스에서 가져옵니다.

단순 name@version 값은 거의 항상 실수이므로 여전히 ERR_PNPM_INVALID_PEER_DEPENDENCY_SPECIFICATION과 함께 거부됩니다:

package.json
{
  "peerDependencies": {
    "lib-a": "lib-a@1.2.3"
  }
}

peerDependenciesMeta#

이 필드는 peerDependencies 필드에 나열된 종속성과 관련된 추가 정보를 나열합니다.

peerDependenciesMeta.*.optional#

이 값을 true로 설정하면 선택한 피어 종속성이 패키지 관리자에 의해 선택 사항으로 표시됩니다. 따라서 소비자가 이를 생략하는 경우 오류가 보고되지 않습니다."

예시:

package.json
{
    "peerDependencies": {
        "foo": "1"
    },
    "peerDependenciesMeta": {
        "foo": {
            "optional": true
        },
        "bar": {
            "optional": true
        }
    }
}

Even though bar was not specified in peerDependencies, it is marked as optional. 따라서 pnpm은 bar의 모든 버전이 괜찮다고 가정합니다. 하지만 foo는 선택 사항이며, 이는 필수 버전 사양에 한해서만 그렇습니다.

publishConfig#

패키지가 압축되기 전에 매니페스트의 일부 필드를 재정의할 수 있습니다. 다음 필드를 재정의할 수 있습니다.

필드를 재정의하려면 해당 필드의 게시용 버전을 publishConfig에 추가하세요.

예를 들어, 다음 package.json은:

package.json
{
    "name": "foo",
    "version": "1.0.0",
    "main": "src/index.ts",
    "publishConfig": {
        "main": "lib/index.js",
        "typings": "lib/index.d.ts"
    }
}

다음과 같이 재정의 되어 게시됩니다.

package.json
{
    "name": "foo",
    "version": "1.0.0",
    "main": "lib/index.js",
    "typings": "lib/index.d.ts"
}

publishConfig.name#

추가된 버전: v11.18.0

워크스페이스의 매니페스트에 있는 이름과 다른 이름으로 패키지를 게시합니다. 이는 게시할 이름을 이미 형제 프로젝트가 사용하고 있어서, 그렇지 않으면 게시 직전에 빌드 단계에서 이름을 바꿔야 하는 프로젝트를 위한 것입니다.

package.json
{
  "name": "foo-v2",
  "version": "2.0.0",
  "publishConfig": {
    "name": "foo"
  }
}

Only the published artifact is renamed. Dependents, pnpm-lock.yaml, and release tooling keep addressing the project by its manifest name. 새 이름은 패킹된 매니페스트, tarball 파일 이름, 그리고 레지스트리에서 패키지를 참조하는 모든 것에 적용됩니다: pnpm publish -r의 이미 게시됨 확인 및 레지스트리 선택, 그리고 pnpm change status와 pnpm version -r의 릴리스 계획 확인이 이에 해당합니다.

publishConfig.executableFiles#

기본적으로, 이식성을 위해, bin 필드에 나열된 파일을 제외한 어떤 파일도 결과 패키지 아카이브에서 실행 가능한 것으로 표시되지 않습니다. executableFiles 필드를 사용하면 bin 필드를 통해 직접 접근할 수 없더라도 실행 플래그(+x)가 설정되어야 하는 추가 파일을 선언할 수 있습니다.

package.json
{
  "publishConfig": {
    "executableFiles": [
      "./dist/shim.js"
    ]
  }
}

publishConfig.directory#

publishConfig.directory 필드를 사용하여 현재 package.json을 기준으로 게시되는 하위 디렉터리를 사용자 지정할 수도 있습니다.

지정된 디렉터리에는 현재 패키지의 수정된 버전이 있어야 합니다(일반적으로 서드파티 빌드 도구를 사용합니다).

이 예시에서 "dist" 폴더에는 반드시 package.json이 있어야 합니다

package.json
{
  "name": "foo",
  "version": "1.0.0",
  "publishConfig": {
    "directory": "dist"
  }
}

publishConfig.linkDirectory#

  • 기본값: true
  • 유형: Boolean

true로 설정하면 로컬 개발 중에 프로젝트가 publishConfig.directory 위치에서 심볼릭 링크됩니다.

예시:

package.json
{
  "name": "foo",
  "version": "1.0.0",
  "publishConfig": {
    "directory": "dist",
    "linkDirectory": true
  }
}