[ 살펴보기 ] NPM - Package.json
![[ 살펴보기 ] NPM - Package.json](https://cdn.hashnode.com/res/hashnode/image/upload/v1715695482021/5810ea9f-6a63-4496-8fce-bfe7f71dc67d.jpeg)
우선 NPM은 크게 다음 두 가지를 뜻한다 Javascirpt package를 배포하고 관리할 수 있는 registry, 특정 package를 다운받거나 삭제 등의 동작을 할 때 사용하는 command line interface
프론트엔드 혹은 백엔드를 Javascript로 개발을 한다면 NPM을 통해 package를 받아 프로젝트에 사용해본 적이 있을 것이다. 그리고 설치되는 package와 함께 존재하는 package.json은 무엇일까? 오늘 포스트를 통해 package.json에 대해 살펴보자
만약 내가 새로운 javascript library를 만들어 npm에 올리려고 한다면 package.json에는 내가 올리려고 하는 package에 필요한 정보가 들어갈 것이다 ( 이름, version, peerDependencies 등 )
아니면 만들고 있는 application에 필요한 dependency관리를 npm으로 한다면 package.json은 해당 프로젝트를 설치하여 실행할 때 필요한 정보 등을 담고 있을 것이다 ( scripts, dependencies, devDependencies 등 )
이렇듯 package.json에는 현재 작업하고 있는 package 또는 application의 정보가 담겨진다. Npm이외에 주류로 사용되는 Javascript package manager는 yarn와 pnpm이 존재하지만 두 package manager는 별개의 series에서 살펴보기로 하자.
Package.json
기본적인 package.json은 다음과 같은 형태를 가지고 있다. 아래의 예제를 Vite를 통해 React 프로젝트를 초기 설정했을 때 나오는 package.json 파일이다
{
"name": "react_vite",
"private": true,
"version": "1.2.3",
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"lint": "eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"preview": "vite preview"
},
"dependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.14.1"
},
"devDependencies": {
"@types/react": "^18.0.37",
"@types/react-dom": "^18.0.11",
"@typescript-eslint/eslint-plugin": "^5.59.0",
"@typescript-eslint/parser": "^5.59.0",
"@vitejs/plugin-react": "^4.0.0",
"eslint": "^8.38.0",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.3.4",
"typescript": "^5.0.2",
"vite": "^4.3.9"
}
}
name
name property는 현재 application or package의 이름을 정한다. 만약 해당 프로젝트를 package화 해서 npm에 배포한다면 name property에 설정한 값이 배포한 npm package의 이름이 된다
private
private이 true로 설정되어 있으면 npm public registry에 publish되지 않는다. 만약 package를 npm public registry에 publish하지 않고 사내 에서 사용하기 위해 npm private registry에 publish하고자 한다면 private을 true로 맞추어 놓아야 한다. ( private registry 사용을 위해선 npm 유료 plan으로 업그레이드가 필요하다 )
version
version property는 해당 package의 현재 version을 의미한다. 1.2.3 과 같은 형태를 가지고 있으며 제일 첫 번째 숫자 ( 예제에서는 1 )는 major version, 두 번째 숫자 ( 예제에서는 2 )는 minor version 그리고 마지막 숫자는 patch version을 뜻한다
patch version은 package의 버그 수정과 같은 사항이 업데이트 되었을 때, minor version은 package에 기능이 추가 되었을 때, major version은 이전 major version과는 다른 큰 변화가 적용되었을 때 주로 변경이 된다
type
Node는 ECMAScript modules과 CommonJS module 두 가지 module system을 취급한다. type 속성을 통해 import 또는 export하는 각각의 module을 어떤 module 형식으로 사용할 것인지 정한다 ( 어떤 module이냐에 따라 import, export하는 문법이 다르다 )
type:"module" 이라고 지정하면 Node는 각각의 script 파일을 ECMAScript module로 취급하고 type:"commonjs"라고 지정하면 Node는 각각의 script 파일을 CommonJS module로 취급한다
scripts
사용자 정의 command를 script property에 설정하여 사용할 수 있다.
...
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"lint": "eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"preview": "vite preview"
},
...
위의 package.json 예제와 같이 설정을 하면 application build를 위해 build라는 사용자 정의 command가 정의되어 있는 것을 확인할 수 있다. 그렇기에 npm run build라는 command를 입력하면 build에 정의된 명령어가 실행된다
dependencies
현재 package 또는 application을 정상적으로 실행시키기 위해 필요한 다른 package의 list다.
"dependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.14.1"
},
version 숫자 앞에 ^나 ~와 같은 기호가 있는 것을 확인할 수 있는데 의미는 다음과 같다
Carets (^) 기호는 주어진 package.json 정보를 기반으로 npm install을 통해 package를 local에 설치할 때 해당 library의 새로운 version의 package를 설치하며 이 때 허용되는 version의 범위는 minor version까지다. 즉 위의 react package를 예로 들자면, package.json에는 ^18.2.0로 기입되어 있지만 만약 18.3.0의 새로운 version이 publish되어 설치 가능하다면 실제 설치는 18.3.0 version을 설치한다 하지만 19.0.0과 같이 major version을 변경되었을 때는 새로운 version을 설치하지 않는다. ( minor version 기준 가장 최신 package를 설치 )
반면 Tilde ( ~ ) 기호는 새로운 package가 publish되어 사용가능 하다면 새로운 version으로 설치하되 그 범위가 patch version으로 한정된다. 즉 18.2.3 이나 18.2.5와 같인 patch version이 새로운 package가 배포되어 설치할 수 있으면 설치하되 18.3.0과 같이 minor version이 변경되어 배포된 경우 설치하지 않는다. ( patch version 기준 가장 최신 package를 설치 )
devDependencies
devDependencies도 dependencies와 같이 설치한 package에 대한 정보를 담고 있다. 다만 devDependencies는 application의 실행환경이 아닌 개발환경에서만 필요한 package 정보를 담고 있다
다음은 Vite로 project를 초기화 했을 때 기본적으로 설정되는 devDependencies 내용이다
"devDependencies": {
"@types/react": "^18.0.37",
"@types/react-dom": "^18.0.11",
"@typescript-eslint/eslint-plugin": "^5.59.0",
"@typescript-eslint/parser": "^5.59.0",
"@vitejs/plugin-react": "^4.0.0",
"eslint": "^8.38.0",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.3.4",
"typescript": "^5.0.2",
"vite": "^4.3.9"
}
peerDependencies
만약 지금 실제 application이 아니라 npm에 배포할 package를 제작하고 있다면 현재 만들고 있는 package가 의존하고 있는 다른 package가 존재할 것이다. 만약 react 기반의 app에서 사용할 수 있는 library를 제작중이라면 peerDependencies는 react가 된다. 이렇듯 다른 개발자가 사용할 수 있는 package를 개발 중이라면 해당 package가 의존하는 package를 dependencies가 아닌 peerDependencies에 추가해준다
그렇다면 package를 만들어 배포할 때 package가 의존하는 다른 pacakge를 왜 dependencies가 아닌 peerDependencies에 추가하는 것일까? 우리가 React application에 쓸 수 있는 react-slider라는 library를 만들어 npm에 배포하려 한다고 가정해보자. 그렇다면 우리가 만드는 library에 필요한 package 중 하나는 react가 될 것이다.
"dependencies": {
"react": "^18.2.0",
...
},
만약 react-slider를 만들어 배포할 때 위와 같이 peerDependencies가 아닌 dependencies에 react를 추가해서 배포한다면 react-slider를 다운 받아 사용하는 사용자 프로젝트의 dependency는 다음과 같아 질 것이다
node_modules
react
...
react-slider
node_modules
react
문제는 사용자 root node_modules에는 이미 react가 설치되어 있어도 react-slider의 package.json의 dependencies에 react가 추가되어 있기 때문에 library level에서 해당 package를 한번 더 설치한다. 그리고 이를 방지하기 위해서 다른 사람이 설치해서 사용할 package를 제작할 때 해당 package가 의존하는 다른 package는 dependencies가 아닌 peerDependencies에 추가하여 관리하는 것이다.
"peerDependencies": {
"react": "^18.2.0",
...
},
만약 위와 같이 peerDependencies에 추가를 하고 해당 package를 사용자가 설치했을 때 사용자 프로젝트에 이미 위의 peerDependencies와 호환될 수 있는 version의 react가 설치되어 있다면 react를 추가로 설치하지 않는다. 하지만 사용자 프로젝트에 react가 이미 설치되어 있지 않다면 자동으로 설치해준다 ( npm 7 버전 이후로 자동으로 설치해준다 )
![[ 살펴보기 ] RDB - Relationships](https://cdn.hashnode.com/res/hashnode/image/upload/v1739711556668/48dc9e84-a621-42aa-9c9f-5fc5c436f0ec.jpeg)
![[ 살펴보기 ] MySQL - Data types](https://cdn.hashnode.com/res/hashnode/image/upload/v1739593589113/530f8704-4d27-42c9-a451-bb5c63150b99.jpeg)
![[ 살펴보기 ] TypeORM - Transactions, Migration](https://cdn.hashnode.com/res/hashnode/image/upload/v1739106042581/980b8133-61d4-406a-a026-65be9c28eace.jpeg)
![[ 살펴보기 ] TypeORM - Relations](https://cdn.hashnode.com/res/hashnode/image/upload/v1738666874402/b688bd0b-b6bb-4f43-87d8-c1b46b59f1b7.jpeg)
![[ 살펴보기 ] TypeORM - Basics](https://cdn.hashnode.com/res/hashnode/image/upload/v1738666803591/bef5df17-7dc7-4123-ae55-004d5042df39.jpeg)