- Published on
package.json 정리
- Authors
- Name
- sulmo
exports와 files 옵션
exports
와 files
**
**1. exports
- 목적: 다른 워크스페이스에서 특정 파일들만 노출하거나, API 표면만 제한적으로 공개하고 싶을 때.
- 장점:
- 패키지 외부에서 사용할 수 있는 경로를 명시적으로 제어.
- 노출할 경로를 지정하여 의도치 않은 파일 사용을 방지.
- ESM과 CommonJS 모듈 시스템을 동시에 지원 가능.
{
"type": "module", // 기본 모듈 타입을 ESM으로 설정
"exports": {
"./module": {
"require": "./dist/module.cjs", // CJS 파일
"import": "./dist/module.js" // ESM 파일
}
}
}
// 위와 같이 모듈타입별로 파일을 작성하여 내보내야한다.
- 단점:
- 모든 사용 가능한 파일 경로를 세밀히 정의해야 하므로, 관리 포인트가 늘어날 수 있음.
예: 특정 경로만 노출하고 싶다면 다음과 같이 설정:
{
"exports": {
".": "./index.js",
"./utils": "./src/utils.js",
"./config": "./src/config.js"
}
}
- 이렇게 하면,
require('package-name/utils')
는 동작하지만,require('package-name/src/other-file.js')
는 접근할 수 없음.
files
가 적합한 경우
- 목적: 패키지를 **배포(npm publish)**하거나, 디스크 공간을 절약하고자 특정 파일만 포함하려고 할 때.
- 장점:
- 배포 크기를 줄이기 위해 필요한 파일만 포함 가능.
- 외부 사용과는 무관하며, 배포 아카이브의 크기 최적화에 도움.
- 단점:
- 파일 노출에는 영향을 미치지 않음. 단지 배포 크기만 제어.
예: 필요한 파일만 배포하고 싶다면 다음과 같이 설정:
{
"files": ["index.js", "src/", "config/*.json"]
}
- 이렇게 하면
index.js
,src/
디렉토리, 그리고config
디렉토리의.json
파일만 배포됩니다. - 하지만 파일이 배포되었더라도,
exports
가 정의되어 있으면 접근 제한이 적용됩니다.
exports
가 더 적합
모노레포에서는 보통 - 다른 워크스페이스에서 사용할 때도 API 표면만 노출하고 나머지 파일을 숨길 필요가 있기 때문.
- 모듈이 확장될 경우, 특정 경로가 외부에 노출되거나 의도치 않은 파일을 참조할 위험을 줄일 수 있음.
2. 아무 세팅도 안 되어 있으면 기본 동작은?
exports
가 없는 경우
a) - 모든 파일이 노출됩니다.
- 다른 워크스페이스나 외부 패키지에서
require()
또는import
로 패키지 내부의 모든 파일과 경로에 접근할 수 있습니다. - 예를 들어, 아래와 같은 디렉토리 구조라면:
package/
├── index.js
├── utils/
│ ├── helper.js
└── config/
└── settings.json
다른 워크스페이스에서 다음과 같이 모두 접근 가능합니다:
const helper = require('package/utils/helper')
const settings = require('package/config/settings.json')
files
가 없는 경우
b) - 기본적으로
.npmignore
(또는.gitignore
) 파일이 적용됩니다. .npmignore
가 없으면, 모든 파일이 npm 패키지에 포함됩니다.- 그러나 파일이 배포되더라도, 이는 노출 범위와는 무관하며, 실제로 다른 워크스페이스에서 파일을 사용 가능 여부는 exports 설정 여부에 따라 결정됩니다.
exports
와 files
모두 없는 경우
c) - Node.js: 모든 파일이 노출됩니다.
- npm 배포:
.npmignore
나 기본 규칙에 따라 모든 파일이 포함됩니다.
3. 모노레포에서 최적의 설정
모노레포에서 다른 워크스페이스가 패키지를 참조할 때 exports
를 설정하는 것이 더 중요합니다.files
는 주로 npm registry로 배포할 때 크기를 줄이기 위한 용도로 사용됩니다.
권장 설정
필요한 API 표면만 노출 (
exports
):- 내부 구현 파일이 외부에서 참조되지 않도록 보호.
- 패키지의 명확한 API 표면을 제공.
- 예:
{
"exports": {
".": "./index.js",
"./utils": "./src/utils.js",
"./config": "./src/config.js"
}
}
배포 크기 제어 (
files
):- 불필요한 파일을 배포에서 제외.
- 예:
{
"files": ["index.js", "src/", "README.md"]
}
ESM 및 CommonJS 동시 지원:
- 모듈 시스템 간 호환성을 고려.
- 예:
{
"type": "module",
"exports": {
".": {
"import": "./index.mjs",
"require": "./index.cjs"
}
},
"main": "./index.cjs"
}
peerDependencies
peerDependencies
vs dependencies
vs devDependencies
dependencies
: 패키지가 동작하기 위해 반드시 설치되어야 하는 의존성.devDependencies
: 개발 환경에서만 필요한 의존성 (예: 빌드 도구, 테스트 라이브러리).peerDependencies
: 패키지가 다른 패키지와 함께 동작하도록 요구하는 의존성. 설치는 사용자에게 맡김.
"사용자에게 설치를 맡긴다"의 의미
peerDependencies
는 의존성 패키지가 설치될 환경(사용자의 프로젝트)에 따라 다른 버전이 필요할 수 있는 경우에 사용됩니다. 따라서 패키지를 사용하는 최종 사용자가 직접 해당 패키지를 명시적으로 설치하도록 설계된 것입니다.
예시
라이브러리 제작자의 입장:
json
복사편집
{ "name": "my-library", "peerDependencies": { "react": "^17.0.0" } }
my-library
는react
가 필요하다고 명시합니다.- 하지만
react
를 직접 설치하지 않습니다. (프로젝트의 React 버전은 사용자에 따라 다를 수 있기 때문입니다.)
라이브러리를 사용하는 사용자 입장:
- 사용자가
my-library
를 설치할 때,react
가 프로젝트에 없으면 npm은 경고를 출력하거나(혹은 npm 7 이상에서는 충돌하지 않는 범위에서 자동 설치) 오류를 발생시킵니다. - 사용자는 명시적으로 자신의 프로젝트에 맞는
react
버전을 설치해야 합니다. bash 복사편집npm install react@17 react-dom@17
- 사용자가