package.json

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

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

engines#

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

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

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

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

engines.runtime#

버전 10.21.0에서 추가됨

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

{
  "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을 추가할 수 있습니다:

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

같은 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. 스크립트는 로컬 런타임을 사용하므로 환경 간 일관성이 보장됩니다.

dependenciesMeta#

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

dependenciesMeta.*.injected#

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

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

예를 들어, 다음 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을 다음과 같이 구성할 수 있습니다:

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

반면 form의 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 라이프사이클 스크립트를 사용할 수도 있습니다. pnpm-sync 및 pnpm-sync-dependencies-meta-injected와 같은 서드파티 도구는 주입된 종속성을 업데이트하기 위한 더 강력하고 효율적인 솔루션과 감시 모드 지원을 제공합니다.

peerDependenciesMeta#

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

peerDependenciesMeta.*.optional#

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

예시:

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

bar가 peerDependencies에 지정되지 않았더라도 선택 사항으로 표시된다는 점에 유의하세요. 따라서 pnpm은 bar의 모든 버전이 괜찮다고 가정합니다. 하지만 foo는 선택 사항이지만, 필수 버전 사양에 대해서만 해당됩니다.

publishConfig#

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

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

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

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

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

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

publishConfig.executableFiles#

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

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

publishConfig.directory#

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

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

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

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

publishConfig.linkDirectory#

  • 기본값: true
  • 유형: Boolean

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

예시:

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