새로운 프로젝트나 패키지를 만들 때 가장 먼저 하는 일은 npm 프로젝트로 초기화 해주는 명령어 npm init
을 실헹하는 것이다. 이때 package.json
파일이 생성되는데 언뜻 봐도 프로젝트에 대한 정보를 담고 있는 중요한 파일처럼 보인다. package.json
은 어떻게 사용되는 파일일까?
Node.js 프로젝트에서는 많은 패키지를 사용하게 되고 패키지의 버전도 빈번하게 업데이트 되므로, 프로젝트가 의존하고 있는 패키지를 일괄적으로 관리할 필요가 있다.
npm은 package.json
파일을 통해서 프로젝트의 정보와 패키지 의존성(dependency)을 관리한다. package.json
파일에는 이 프로그램을 실행시키기 위해 필요한 모듈들에 대한 정보와, 프로그램을 실행시키는 방법, 프로그램을 테스트하는 방법 등이 명시되어 있다.
package.json
파일을 이용하면 협업 시 동일한 개발 환경을 빠르게 구축할 수 있다는 장점이 있다.
프로젝트의 루트 디렉토리에서 npm init
명령어를 실행하면 package.json
파일이 생성된다.
-y
또는 --yes
옵션을 추가하면 기본 설정값으로 생성된다.
npm init
# 기본 설정값 적용
npm init -y
npm init --yes
npm init -y
를 실행하면 아래와 같이 기본 설정값이 적용된 package.json
파일이 생성된다.
{
"name": "test-for-studying",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
각 프로퍼티는 JSON 형식의 key: value 형태로 구성된다.
name과 version을 통해서 각 패키지의 고유성을 판별하기 때문에, 배포될 패키지라면 이 두 프로퍼티가 가장 중요하다.
프로젝트의 이름.
{
"name": "test-for-studying",
}
name을 정할 때는 몇 가지 규칙을 따라야 한다.
.
(점) 또는 _
(언더스코어)로 시작 불가require()
함수의 인수로 전달되기 때문)프로젝트 버전.
{
"version": "1.0.0",
}
패키지의 내용이 변경되면 version도 변경해줘야 한다.
version은 메이저 버전 번호, 마이너 버전 번호, 패치 버전 번호로 구성되며, node-semver로 파싱할 수 있어야 한다.
버전 정보는 아래와 같이 유의적으로 구성되어 있다.
버전 정보 앞에 기호를 부여하면 업데이트 범위를 지정할 수 있다.
표기법 | 설명 |
---|---|
version | 명시된 version과 일치 |
>version | 명시된 version보다 높은 버전 |
>=version | 명시된 version과 같거나 높은 버전 |
<version | 명시된 version보다 낮은 버전 |
<=version | 명시된 version과 같거나 낮은 버전 |
~version | 명시된 version과 근사한 버전 (패치 버전 범위 내) |
^version | 명시된 version과 호환되는 버전 (마이너 버전 범위 내) |
~
(틸드): 패치 버전 범위 내에서 업데이트 (ex.~0.1.1
: 0.1.1 <= version < 0.2.0)
^
(캐럿): 마이너 버전 범위 내에서 업데이트 (ex.^1.0.2
: 1.0.2 <= version < 2.0.0)
프로젝트 설명.
{
"description": "An example module to study the usage of package.json",
}
문자열로 작성한다.
npm search
로 검색된 리스트에 표시되기 때문에 사람들이 패키지를 발견하는데 도움이 된다.
프로젝트 검색에 참조되는 키워드.
{
"keywords": [
"example",
"study",
],
}
배열 안에 문자열로 작성한다.
npm search
로 검색된 리스트에 표시되기 때문에 사람들이 패키지를 발견하는데 도움이 된다.
라이센스 명시.
{
"license": "ISC"
}
프로젝트를 배포하는 경우 라이센스가 일부 사용자의 소프트웨어 사용을 제한할 수 있기 때문에 매우 중요하다. 명확한 라이센스를 사용하면 어떤 조건에서 사용할 수 있는지 명확하게 정의할 수 있다. 일반적으로 라이센스 식별자 코드("MIT", "ISC"와 같은 문자열)로 작성한다.
다른 사용자에게 사용 권한을 부여하지 않으려면 아래와 같이 명시한다.
{
"license": "UNLICENSED",
}
private 프로퍼티를 true로 설정하면 비공개 repository가 배포되지 않도록 미연에 방지할 수 있다.
프로젝트 작성자 정보.
{
"author": {
"name": "Lian Kim",
"email": "5@gmail.com",
"url": "https://velog.io/@liankim"
},
}
한 사람만 지정할 수 있으며, name은 필수, email과 url은 선택이다.
"name <email> (url)"
형식을 사용하면 문자열 하나로 기술할 수도 있다.
아래와 같이 형식을 지켜 하나의 문자열로 묶으면 npm이 파싱해준다.
{
"author": "Lian Kim <liankim@example.com> (https://velog.io/@liankim)"
}
또한 npm은 author 프로퍼티를 바탕으로 최상위 "maintainers" 필드에 npm user info를 설정한다.
프로젝트 기여자 정보.
{
"contributors": [
{
"name": "Leah Kim",
"email": "leahkim@example.com"
},
{
"name": "Nayoung Kim",
"email": "nayoungkim@example.com"
},
],
}
배열 안에 여러 사람을 지정할 수 있다.
프로젝트의 시작점이 되는 모듈 지정 (미지정 시 프로젝트의 루트에 있는 index.js
가 디폴트)
{
"main": "index.js",
}
예를 들어, "foo"라는 패키지를 설치한 사용자가 require("foo")
를 실행하면, main으로 지정된 모듈의 exports 객체가 반환된다.
프로젝트의 소스 코드가 관리되는 저장소 위치.
{
"repository": {
"type": "git",
"url": "https://github.com/npm/cli.git"
},
}
소스 코드에 참여하고자 하는 사람들에게 도움이 될 수 있다.
url은 특별한 조작없이 VCS 프로그램에서 바로 다뤄질 수 있도록 오픈되어 있어야 하고, 프로젝트의 홈페이지 url을 명시하면 안된다.
package.json
파일이 루트 디렉토리가 아닌 다른 곳에 위치한다면 디렉토리를 명시해줘야 한다.
{
"repository": {
"type": "git",
"url": "https://github.com/facebook/react.git",
"directory": "packages/react-dom"
},
}
GitHub, GitHubist, Bitbucket 또는 GitLab repository의 경우, npm install
사용 시와 동일하게 shorcut 구문을 사용할 수 있다.
{
"repository": "npm/npm",
"repository": "github:user/repo",
"repository": "gist:11081aaa281",
"repository": "bitbucket:user/repo",
"repository": "gitlab:user/repo",
}
자주 실행하는 npm 명령어 등록.
{
"scripts": {
"start": "node index.js",
"test": "standard"
},
}
key는 스크립트 이름이고, value는 실행할 사용자 정의 명령이다.
프로젝트에서 자주 실행해야 하는 명령어를 scripts에 작성해두면 npm run 명령어로 실행할 수 있다.
npm run <script-name>
start
: 만약 프로젝트의 루트에 server.js
파일이 존재하면, npm은 기본적으로 start
명령어를 사용했을 때 node server.js를 실행한다.install
: 만약 프로젝트의 루트에 binding.gyp
파일이 존재하면, npm은 기본적으로 install
명령어를 사용했을 때 node-gyp을 사용해서 컴파일한다.{
"scripts": {
"start": "node server.js",
"install": "node-gyp rebuild",
},
}
프로덕션 환경에서(런타임 시) 필요한 패키지 관리.
{
"dependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
}
이 패키지를 실행하는 데 필요한 다른 패키지의 이름과 버전이 포함된다.
npm CLI를 사용하여 패키지를 설치하면 node_modules
디렉토리에 패키지가 저장되고, package.json
파일의 dependencies에 설치한 패키지의 이름과 버전이 명시된다.
애플리케이션을 설치할 때(npm install
) dependencies를 참조하여 필요한 확장 모듈을 자동으로 설치한다.
개발 단계에서만 필요한 패키지 관리.
{
"devDependencies": {
"@babel/cli": "^7.18.10",
"@babel/core": "^7.19.0",
"@babel/preset-env": "^7.19.0",
"@babel/preset-react": "^7.18.6",
"babel-loader": "^8.2.5",
"html-webpack-plugin": "^5.5.0",
"webpack": "^5.74.0",
"webpack-cli": "^4.10.0",
"webpack-dev-server": "^4.11.0"
}
}
개발, 테스트 시에는 필요하지만 런타임 시에는 필요 없는 패키지들이 포함된다.
예를 들어, babel 같은 트랜스파일러나 webpack 같은 번들러의 경우 빌드 시에만 필요하기 때문에 설치할 때 -D
(--save-dev) 옵션을 추가하여 devDependencies에서 관리한다.
{
"private": true,
}
true로 설정하면 publish 명령을 거부하기 때문에 패키지가 배포되지 않는다.
비공개 repository가 실수로 배포되지 않도록 방지하는 방법이다.
실행 가능한 노드 버전의 범위를 지정 (미지정 시 모든 버전이 해당됨)
사용자가 engine-strict config flag 미설정 시, 이 필드는 조언 용도로만 사용된다.
{
"engines": {
"node": ">=0.10.3 <15"
}
}
npm 버전도 지정할 수 있다.
{
"engines": {
"npm": "~1.0.20"
}
}
package-lock.json
파일은 node_modules
트리나 package.json
파일이 수정되면 자동으로 생성되거나 업데이트되는 파일이다. package-lock.json
파일이 작성된 시점의 의존성 트리에 대한 정확한 정보를 가지고 있다.
package.json
파일에서는 패키지의 버전을 지정할 때 version range의 형태로 특정 버전이 아닌 버전의 범위를 지정한다(ex. ^18.2.0
). 협업 시 같은 package.json
을 사용해 동일한 개발환경을 구성하게 되는데, version range로 지정된 경우 업데이트된 버전이 설치되면서 에러를 발생시킬 수 있다. 이렇게 되면 같은 package.json
을 사용하여 npm install을 진행하더라도 서로 다른 node_modules
가 생성될 수 있다.
package.json의 dependencies
package-lock.json의 dependencies
만약 package.json
에 패키지 버전을 정확히 명시하게 된다면, 프로젝트에서 사용하고 있는 패키지가 패치될 때마다 프로젝트의 package.json
파일에 명시된 버전도 수정해줘야 한다. version range를 명시함으로써 사용하는 모든 패키지들의 릴리즈를 항상 추적하고 수정해야 하는 번거로움을 해결할 수 있다.
package-lock.json
파일이 존재하면, npm은 package.json
파일 대신 package-lock.json
파일을 사용하여 node_modules
를 생성한다.
의존성을 특정된 버전으로 동일하게 설치해줌으로써 동일한 개발환경 세팅을 도와주는, 협업 시 아주 중요한 파일이다. 따라서 package-lock.json
파일도 같이 커밋하는 것을 권장한다. (node_modules
없이 배포하는 경우 반드시 필요)
참고 자료
npm Docs package.json package-lock.json
PoimaWeb 모듈화와 npm
https://velog.io/@songyouhyun/Package.json과-Package-lock.json의-차이