기타/npm

npm이란? & package.json의 dependencies vs devDependencies vs peerDependencies vs ...

둉이 2022. 9. 26. 21:33

npm 로고

npm(= Node Package Manager)은 Node.js의 기본 패키지 관리자로, 패키지를 설치하고 관리할 수 있는 여러 기능을 제공한다.

 

npm은 package.json을 통해 프로젝트의 정보를 저장하고, 의존하는 패키지 버전 정보를 관리한다.

 

package.json 파일을 열어 보면, 다음과 같이 라이브러리의 의존성 관리와 관련된 부분을 발견할 수 있다.

{
  "dependencies": {
    "@charlietango/use-native-lazy-loading": "^1.9.0",
    "@repacks/next-pack": "^10.0.1",
    "@vercel/fetch": "^6.1.1",
    "abort-controller": "^3.0.0",
    "classnames": "^2.3.1",
    "clean-deep": "^3.4.0",
    "compression": "^1.7.4",
    "cookie-parser": "^1.4.5",
    "cors": "^2.8.5",
    "dayjs": "^1.10.4",
    "dequal": "^2.0.2"
  },
  "devDependencies": {
    "cross-env": "^7.0.3",
    "npm-run-all": "^4.1.5"
  },
  ...
}

 

 

여기서 궁금한 점이 생겼다.

 

dependenciesdevDependencies는 왜 분리되어 있는 걸까? 그리고 정확한 분리 기준은 무엇일까?

 

 

dependencies와 devDependencies는 실제 서비스에서 사용할 모듈과 개발 단계에서만 사용할 모듈을 분리하는 용도의 속성이다.

 

분리하는 이유로는 빌드 시간 및 어플리케이션 크기를 줄이기 위함이다.

 

프로덕션 빌드 및 배포된 모듈의 의존성을 설치할 때, dependencies에 위치한 패키지만 번들에 포함되기 때문이다.

 

이제 각각의 차이에 대해 알아보자.

 

 

dependencies

프로덕션 환경 및 서비스 런타임에 사용되는 일반적인 종속성을 가진 라이브러리가 위치한다.

 

npm install 라이브러리 명령어로 설치가 가능하다.

 

dependencies에서 관리하는 라이브러리의 예시로는 서비스 로직과 관련된 라이브러리, React, 상태 관리 라이브러리(Recoil, Redux 등)이 있다.

 

 

devDependencies

로컬 개발환경 혹은 프로젝트 빌드에만 필요하거나 서비스 로직과 관련 없는 개발 종속성을 가진 라이브러리가 위치한다.

 

npm install --save-dev 라이브러리 혹은 npm install -D 라이브러리 명령어로 설치가 가능하다.

 

devDependencies에 속한 라이브러리는 프로덕션 모드로 의존성을 설치할 경우(npm install --production 명령어)와 npm에 배포된 패키지를 설치하는 경우에는 다운로드 대상에 포함되지 않는다.

 

devDependencies에서 관리하는 라이브러리의 예시로는 webpack, testing libraries, 타입 관련 라이브러리(typescript, @types/*), eslint, storybook 등이 있다.

 

 

 

 

dependencies와 devDependencies 외에도 많이 사용되지는 않지만 의존성 관리를 위한 추가적인 속성으로 peerDependencies, optionalDependencies, bundledDependencies 등이 있다.

 

peerDependencies

"peerDependencies": {
  "react": ">=16.8.0",
  "react-dom": ">=16.8.0"
},

사용 중인 라이브러리에서 다른 라이브러리의 특정 버전에 종속성을 갖는 경우에 이를 명시하기 위한 속성으로, 런타임에 필요하지만 직접 의존성을 관리하지 않는 라이브러리가 위치한다.

 

npm install --save-peer 라이브러리 명령어로 설치가 가능하다.

 

런타임에서 React나 jQuery 같은 특정 라이브러리의 플러그인을 사용하고 해당 플러그인이 특정 버전에 의존할 경우, peerDependencies 내에 의존성을 갖는 라이브러리의 이름과 버전을 명시하여 오류가 발생하지 않도록 하는 용도로 사용한다.

 

npm@3.0 이후부터는 peerDependencies에 속한 라이브러리를 직접 import하여 사용하지는 않지만, 명시된 버전으로 설치되어 있지 않은 경우에는 경고 메시지가 표출된다.

(npm@3.0 이전까지는 누락되거나 낮은 버전의 의존성을 갖는 경우 peerDependencies 내 라이브러리를 직접 설치했으며, 종속성 충돌 시 오류가 발생)

 

 

optionalDependencies

"optionalDependencies": {
  "dayjs": "^1.11.5"
}

말 그대로 선택적인 종속성을 갖는 라이브러리를 포함한다.

 

optionalDependencies에서 관리하는 라이브러리는 설치에 실패했다고 하더라도 별다른 에러가 발생하지 않는다.

 

따라서, 해당 종속성이 설치되지 않았더라도 프로젝트 실행에 문제가 없도록 대비가 되어야 한다.

 

npm install --save-optional 라이브러리 명령어로 설치가 가능하다.

 

 

bundledDependencies

"bundledDependencies": ["renderized"]

패키지를 번들링할 때 번들에 포함시키고자 하는 패키지의 이름들을 명시할 때 사용하는 속성이다.

 

사용 예시는 다음과 같다.

 

- npm 레지스트리에 존재하지 않거나 수정된 라이브러리를 사용하고자 하는 경우

 

- 자신의 프로젝트를 모듈로 재사용하려는 경우

 

- 모듈과 함께 일부 파일을 배포하고자 하는 경우

 

 

extensionDependencies

"extensionDependencies": ["esbenp.prettier-vscode"]

IDE 익스텐션에 대한 의존성을 명시할 때 사용하는 속성이다.

 

익스텐션 ID는 ${publisher}.${name} 형태로 명시하면 된다.

 

vscode의 경우에는 EXTENSIONS 메뉴에서 마우스 오른쪽 버튼 - Copy Extension ID를 클릭하면 익스텐션 ID를 얻을 수 있다.

vscode - Extension - Copy Extendion ID

 

 

 

 

dependencies 관련된 부분 외에도 package.json는 프로젝트 이름이나 버전 등 많은 정보를 포함하고 있다.

 

그 외 속성들에 대해서도 간단하게 정리했다.

 

 

그 외 속성들

패키지 속성에서 가장 중요한 부분은 name과 version이다.

{
  "name": "corner-smiledelivery-fe",
  "version": "1.0.0",
  "description": "This is corner smiledelivery frontend project.",
  "keywords": ["corner", "smiledelivery", "shopping"]
}

 

이 두 값을 사용하여 고유한 식별자를 형성하여 패키지를 구분하기 때문에 필수적으로 package.json에 명시해야 한다.

(패키지를 npm에 게시하지 않는다면 선택 사항)

 

name

프로젝트(패키지) 이름

이름은 214자 이하여야 하고 대문자, 안전하지 않은 문자가 포함되면 안됨

 

version

프로젝트(패키지)의 버전 정보

semver 버전 명세에 맞게 버전을 명시해야 함

 

description

프로젝트(패키지)에 대한 설명

npm 목록에서 패키지 검색 시 사용되며, 문자열로 명시

 

keyword

프로젝트(패키지)의 키워드

npm 목록에서 패키지 검색 시 사용되며, 문자열 배열로 명시

 

homepage

"homepage": "https://github.com/owner/project#readme"

프로젝트(패키지)의 홈페이지 주소

주로 github 주소를 사용

 

license

// 올바른 표기 방식
"license": "MIT"

// 올바르지 않은 표기 방식
{
  "license" : {
    "type" : "ISC",
    "url" : "https://opensource.org/licenses/ISC"
  }
}

// 라이센스가 없는 경우
"license": "UNLICENSED"

프로젝트(패키지)의 사용 방법과 제한 사항을 알 수 있는 라이센스 종류

자주 사용되는 라이센스 종류는  BSD-3-Clause, MIT, ISC, GPL-3.0, Apache-2.0 등이 있음

 

bugs

"bugs": {
  "url" : "https://github.com/owner/project/issues",
  "email" : "project@hostname.com"
}

프로젝트에 버그 혹은 이슈를 보고하기 위한 연락처(url, email)

 

repository

"repository": {
  "type": "git",
  "url": "https://github.com/npm/cli.git"
}

 

author

"author": "Barney Rubble <b@rubble.com> (http://barnyrubble.tumblr.com/)"

프로젝트(패키지) 제작자의 이름

 

files

"files": [
  "dist/"
]

패키지가 의존성으로 설치될 때 같이 포함될 파일 목록

생략할 경우에는 모든 파일이 포함

package.json, README.md, LICENSE, main 속성에서 지정한 파일은 설정에 관계 없이 항상 포함

 

main

"main": "index.js",

프로젝트의 진입점이 되는 모듈 파일

기본 값으로는 루트 경로의 index.js를 가짐

 

funding

"funding": {
  "type" : "individual",
  "url" : "http://example.com/donate"
},
// or
"funding": "http://example.com/donate",

프로젝트 후원을 위한 정보를 제공하는 속성

 

engines

"engines": {
  "node": ">=8.0.0 <11.0.0"
},

프로젝트를 올바르게 실행할 수 있는 환경 정보를 명시하는 속성

 

scripts

"scripts": {
  "start": "export RND_API_HOST='//localhost:8080/v4' && node scripts/start.js",
  "build": "export NODE_ENV='production' && node scripts/build.js",
  "build-staging": "export NODE_ENV='staging' && node scripts/build.js",
  "build-development": "export NODE_ENV='development' && node scripts/build.js",
  "test": "node scripts/test.js --env=jsdom"
},

프로젝트(패키지) 내에서 자주 사용되는 스크립트 명령 모음

키는 수명 주기 이벤트, 값은 해당 시점에서 실행할 명령을 의미

 

private

"private": true

패키지의 private/public 여부 속성으로, 패키지 관리자에 패키지를 게시하지 않으려면 true로 설정하면 된다.

 

config

"config": {
  "port": "8080"
}

패키지 scripts에서 사용할 수 있는 매개변수를 설정하는 속성

$npm_package_config_<variable-name> 형태로 변수 접근 가능

 

 

 

참고 자료

 

Yarn

Fast, reliable, and secure dependency management.

classic.yarnpkg.com

 

 

package.json | npm Docs

Specifics of npm's package.json handling

docs.npmjs.com