HEROPY
Tech
{{ scrollPercentage }}%

처음 시작하는 Node.js 개발 - 2 - npm

nodejs javascript npm

npm(Node Package Manager)은 JavaScript 및 세계 최대의 소프트웨어 레지스트리 패키지 관리자로 Node.js를 설치하면 같이 설치되어 사용할 수 있습니다.
npm에는 Node.js에서 사용되는 각종 코드 패키지들이 모여있고, 우리는 그 패키지를 다운로드 받아 사용할 수 있습니다.
좀 더 쉽게 npm은 Node.js 생태계의 앱스토어나 플레이스토어 같은 역할을 합니다.

npm 레지스트리에는 640,000개가 넘는 패키지가 포함되어 있으며, 패키지는 의존성(dependencies) 및 버전을 추적할 수 있도록 구성됩니다.
이 페이지에서는 npm의 주요 CLI(Command Line Interface)와 관련된 정보들에 대해서 살펴보겠습니다.

init (초기화)

$ npm init
  • package name
  • version
  • description
  • entry point
  • test command
  • git repository
  • keywords
  • author
  • license

여러 가지 질문에 답하면(옵션을 추가하면) package.json 파일을 작성합니다.
각 질문을 넘어가면 기본값을 사용합니다.

질문 없이 바로 시작하고 싶다면 -f(--force), -y(--yes) 중 하나의 플래그를 추가하는 것을 추천합니다.

$ npm init -y

이미 package.json 파일을 가지고 있다면, 먼저 그 파일을 읽고 난 후 옵션을 기본값으로 사용합니다.

package.json

{
  "name": "project-name",
  "version": "1.0.0",
  "keywords": [],
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "HEROPY",
  "license": "MIT",
  "dependencies": {},
  "devDependencies": {}
}

package.json은 프로젝트 정보와 의존성(dependencies)을 관리하는 문서입니다.
이미 작성된 package.json 문서는 어느 곳에서도 동일한 개발 환경을 구축할 수 있게 해줍니다.
JSON 포맷으로 작성해야 하며, 다음과 같은 옵션들이 추가될 수 있습니다.

name

URL이나 Command Line의 일부로 사용될 소문자로 표기된 214자 이내의 프로젝트(패키지) 이름으로, 간결하고 직관적인 이름으로 설정하되 다른 모듈과 동일한 이름을 피하세요.

version

SemVer(The semantic versioner for npm)로 분석 가능한 형태의 버전을 지정합니다.

description

프로젝트(패키지)의 설명을 지정합니다.
(npm search 사용 시 도움이 됩니다.)

keywords

프로젝트(패키지)의 키워드를 배열로 지정합니다.
(npm search 사용 시 도움이 됩니다.)

{
  "keywords:": [
    "array",
    "string"
  ]
}

homepage

프로젝트 홈페이지로 연결되는 URL을 지정합니다.

bugs

패키지에 문제가 있을 때 보고될 이슈 트래커(추적시스템) 및 이메일 주소 등에 대한 URL을 지정합니다.

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

license

패키지 사용을 허용하는 방법과 제한 사항을 알 수 있도록 라이센스를 지정합니다.
Open Source Licenses

author

제작자의 이름을 지정합니다.

files

패키지가 의존성으로 설치될 때 같이 포함될 파일들의 배열입니다.
생략하면 자동 제외로 설정된 파일을 제외한 모든 파일이 포함됩니다

{
  "files": [
    "dist/",
    "js/{src,dist}/",
    "scss/"
  ]
}

main

프로그램의 기본 진입 점(entry point)를 지정합니다.
패키지의 이름이 jquery이고, 사용자가 require('jquery')를 사용하면 진입 점의 메인 모듈에서 exports object가 반환(return)됩니다.

repository

코드가 존재하는 장소를 지정합니다.
GitHub를 사용하면 npm docs 명령을 사용하여 찾을 수 있습니다.

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

script

패키지 라이프 사이클에서 여러 번 실행되는 스크립트 명령을 포함합니다.

{
  "scripts": {
    "lint": "bash lint.sh",
    "dev": "webpack-dev-server",
    "prod": "webpack -p"
  }
}
# `webpack -p` 와 동일
$ npm run prod

dependencies

패키지의 배포 시 포함될 의존성 모듈을 지정합니다.

devDependencies

패키지의 개발 시 사용될 의존성 모듈을 지정합니다.
(배포 시 포함되지 않습니다)

peerDependencies

패키지의 호환성 모듈을 지정합니다.
(npm@3 이후로 배포 시 포함되지 않습니다, 대신 호환성 모듈이 없으면 경고 메시지가 표시됩니다)

{
  "name": "bootstrap",
  "peerDependencies": {
    "jquery": "1.9.1 - 3",
    "popper.js": "^1.12.9"
  }
}

bundledDependencies

패키지를 게시할 때 번들로 묶을 패키지 이름을 배열로 지정합니다.
npm 패키지를 로컬에서 보존해야 하거나 단일 파일 다운로드를 통해 사용할 수있는 경우 npm pack을 실행하여 패키지를 <name>-<version>.tgz 형태의 tarball 파일)로 묶을 수 있습니다.

{
  "bundledDependencies": [
    "renderized",
    "super-streams"
  ]
}

optionalDependencies

npm을 찾을 수 없거나 설치에 실패한 경우 계속 진행하려면 optionDependencies 객체에 넣을 수 있습니다.
dependencies 동일하게 배포 시 포함될 의존성 모듈을 지정하지만, 빌드 실패로 인해 설치 과정이 중단되지 않습니다.

{
  "optionalDependencies": {
    "7zip-bin-mac": "^1.x.x",
    "7zip-bin-win": "^2.x.x"
  }
}

engines

패키지가 작동하는 Node 버전을 지정합니다.

{
  "engines": {
    "node": ">=0.10.3 <0.12",
    "npm" : "~1.0.20"
  }
}

private

개인 저장소의 우연한 발행을 방지하기 위해 npm에서 패키지의 공개 여부를 지정합니다.

{
  "private": true
}

package-lock.json

package.json이 동일한 개발 환경 구축을 위한 정보를 가지고 있지만, 다양한 경우에 의해 동일한 개발 환경 구축에 문제가 발생할 수 있습니다.

예를 들어, 다음과 같은 어떤 상위 모듈(dashdash)에서 사용하는 하위 모듈 중 하나(assert-plus)의 버전이 변경되었다고 가정합니다.
그렇다면 상위 모듈 버전이 동일하다고 하더라도 내부적으로 다른 결과를 출력할 수 있습니다.

{
  "dashdash": {
    "version": "1.14.1",
    "requires": {
      "assert-plus": "1.0.0"
    },
    "dependencies": {
      "assert-plus": {
        "version": "1.0.0"
      }
    }
  }
}

이를 방지하기 위해 npm으로 node_modules의 구성 트리 또는 package.json을 수정하는 모든 작업에 대해 package-lock.json이 자동으로 생성됩니다.
모든 작업에 대해 자동 생성하므로 의존성 업데이트와 같은 버전 변경에 대해서도 동일한 모듈 트리를 생성할 수 있게 됩니다.

install (패키지 설치)

{
  "dependencies": {
    "bootstrap": "^4.0.0",
    "jquery": "^3.3.1"
  },
  "devDependencies": {
    "babel-preset-env": "^1.6.1",
    "node-sass": "^4.7.2"
  }
}

이미 정의된 의존성 모듈 설치

package.json 파일에 이미 정의된 의존성(dependencies) 모듈(Modules)이 있으면, 나열된 모든 모듈을 로컬 node_modules 폴더에 설치합니다.

$ npm install

아직 정의되지 않은 의존성 모듈 설치

--save

프로젝트(패키지)가 배포(Deploy) 시 사용될 의존성 모듈을 정의하고 설치합니다.
--save 플래그(Flag)를 사용하거나 생략합니다.
"dependencies"에 나열됩니다.

npm will –save by default now. Additionally, package-lock.json will be automatically created unless an npm-shrinkwrap.json exists.

  • npm releases note v5.0.0
$ npm install --save <package>  
$ npm install <package>  # npm@5 부터 `--save` 생략 가능
$ npm install <package>@<version>  # 버전 설정
$ npm i <package>  # alias

Example:

$ npm install --save jquery  # jquery ^3.3.1
$ npm install jquery
$ npm install jquery@1.12.4
$ npm i jquery

--save-dev / -D

개발 단계에서만 사용하는 의존성 모듈을 정의하고 설치합니다.
-D(--save-dev) 플래그를 사용합니다.
"devDependencies"에 나열됩니다.

$ npm install --save-dev <package>  
$ npm install -D <package>
$ npm install -D <package>@<version>  # 버전 설정
$ npm i -D <package>  # alias

Example:

$ npm install --save-dev babel-preset-env
$ npm i -D node-sass

--save-optional / -O

선택적 의존성 모듈을 정의하고 설치합니다.
-O(--save-optional) 플래그를 사용합니다.
"optionalDependencies"에 나열됩니다.

--save-exact / -E

npm의 기본 SemVer 연산자(^, ~ 같은)를 사용하는 대신 정확한 버전으로 설치합니다.
-E(--save-exact) 플래그를 사용합니다.
"dependencies"에 나열됩니다.

npm i bootstrap:

{
  "dependencies": {
    "bootstrap": "^4.0.0"
  }
}

npm i bootstrap -E:

{
  "dependencies": {
    "bootstrap": "4.0.0"
  }
}

--save-bundle / -B

번들로 묶을 패키지 의존성 모듈을 정의하고 설치합니다.
-B(--save-bundle) 플래그를 사용합니다.
"bundledDependencies"에 나열됩니다.

전역 설치

패키지를 command line tool로 사용하려면 전역(Global)으로 설치할 수 있습니다.
전역으로 설치된 패키지는 디렉토리에 관계없이 작동합니다.
-g 플래그를 사용합니다.

$ npm install -g webpack

유의적 버전(Semver)이란?

의존성 모듈의 버전을 너무 엄격하거나 느슨하지 않게 관리하기 위해서 npm에서는 Semver(Semantic Versioning)를 지원합니다.

우선 버전을 1.0.0과 같이 X.Y.Z(Major.Minor.Patch) 형식으로 정합니다.
API에 호환되지 않는 변경이라면 Major 버전을 올리고,
API가 호환되면서 바꾸거나 추가하는 경우에는 Minor 버전을 올리고,
API가 영향이 없는 버그 수정은 Patch 버전을 올립니다.
이러한 시스템을 유의적 버전(Semver)이라고 합니다.

범위(Ranges)

{
  "dependencies": {
    "bootstrap": "^4.0.0",
    "jquery": ">=1.12.0"
  }
}

npm은 위 코드의 "^4.0.0", ">=1.12.0"과 같이 연산자(Operator)와 버전(Version)으로 의존성 모듈의 버전 범위(Ranges)를 구성합니다.
주로 사용하는 연산자들은 다음과 같습니다.

연산자 설명
< 버전보다 작은 범위
<= 버전보다 작거나 같은 범위
> 버전보다 큰 범위
>= 버전보다 크거나 같은 범위
= 같은 범위(일반적으로 생략됩니다)
^ (Caret) Minor Level 범위
~ (Tilde) Patch Level 범위

예를 들어, ~4.0.7은 Patch Level 범위인 4.0.0~4.0.99까지는 일치하지만, 4.2.5, 3.0.1 같은 그 외 Level 범위의 버전은 일치하지 않습니다.

사용하고자 하는 의존성 모듈의 버전 범위는 npm semver calculator에서 확인할 수 있습니다.

기타 자주 사용하는 CLI commands

outdated (오래된 패키지 확인)

설치된 패키지가 현재 구형(오래된 패키지)인지 여부를 확인하기 위해 레지스트리를 검사합니다.

$ npm outdated

update (버전 업데이트)

패키지를 Semver에 맞는 최신 버전으로 업데이트합니다.
패키지 이름을 지정하지 않으면 지정된 위치(Global/Local)의 모든 패키지를 업데이트합니다.

$ npm update <package>

# aliases
$ npm up
$ npm upgrade

예를 들어, 다음과 같은 버전 정보를 가지는 jquery 모듈을 업데이트할 경우를 살펴봅시다.

{
  name: 'jquery',
  versions: [
    # ...
    '1.11.1',
    '1.11.2',
    '1.11.3',
    '1.12.0',
    '1.12.1',
    '1.12.2',
    '1.12.3',
    '1.12.4',
    '2.1.0-beta2',
    '2.1.0-beta3',
    # ...
  ]
}

다음과 같이 모듈 버전에 범위 연산자를 ^(Caret)으로 사용했다면, Minor Level 범위에서 가장 최신 버전으로 업데이트합니다.
따라서 1.12.4 버전을 설치합니다.

{
  "dependencies": {
    "jquery": "^1.11.1"
  }
}
$ npm update jquery

이번엔 모듈 버전에 범위 연산자를 ~(Tilde)로 사용한 경우를 봅시다.
Patch Level 범위에서 가장 최신 버전으로 업데이트합니다.
따라서 1.11.3 버전을 설치합니다.

{
  "dependencies": {
    "jquery": "~1.11.1"
  }
}
$ npm update jquery

npm@2.6.1부터 최상위 패키지만 업데이트하고, 이전 버전의 npm은 모든 종속성을 재귀적으로 검사합니다.
이전 동작을 사용하려면 npm --depth 9999 update를 사용하세요.

uninstall (패키지 제거)

설치된 패키지를 제거합니다.
npm install과 동일하게 --save, --save-dev 같은 플래그들을 사용할 수 있습니다.

$ npm uninstall <package>

# aliases
$ npm remove
$ npm rm
$ npm r
$ npm un
$ npm unlink

version (패키지 버전 관리)

자신의 프로젝트(패키지)의 버전을 관리하기 위해서 npm version을 사용합니다.

$ npm version major  # Major 버전을 올립니다.
$ npm version minor  # Minor 버전을 올립니다.
$ npm version patch  # Patch 버전을 올립니다.

-m(--message) 플래그는 버전 커밋(Commit)을 할 때 메시지로 사용합니다.
메시지에 %s가 있으면 버전 번호로 바뀝니다.

$ npm version patch -m "Upgrade to %s for reasons"
# ex> "Upgrade to 1.0.1 for reasons"

ls (패키지 목록)

설치된 패키지를 나열합니다.

$ npm ls

# aliases
$ npm list
$ npm la
$ npm ll

--json

패키지 정보를 JSON 형식으로 표시합니다.

$ npm ls --json

--long

패키지의 확장 정보를 표시합니다.

# ...
├── babel-preset-env@1.6.1
│   A Babel preset for each environment.
│   git+https://github.com/babel/babel-preset-env.git
│   https://babeljs.io/
├── bootstrap@4.0.0
│   The most popular front-end framework for developing responsive, mobile first projects on the web.
│   git+https://github.com/twbs/bootstrap.git
│   https://getbootstrap.com
# ...

--depth

의존성 트리를 표시하는 최대 깊이를 정수(Integer)로 지정합니다.

$ npm ls --depth=1

--prod / --production

dependencies 의존성 모듈만 표시합니다.

--dev

devDependencies 의존성 모듈만 표시합니다.

전역 설치된 패키지 목록

전역 설치된 패키지들의 목록을 나열합니다.

npm ls -g --depth=0

view (패키지 정보 보기)

패키지에 관한 데이터(정보)를 보여줍니다.
필드가 객체이면 JavaScript 객체 리터럴로 출력됩니다.
--json 플래그가 주어지면, JSON 형식으로 출력됩니다.

$ npm view <package> <field>

# aliases
$ npm info
$ npm show
$ npm v

# examples
$ npm view jquery
$ npm view jquery --json
$ npm view lodash license
$ npm view express contributors[0].email

참고 자료(References)

https://docs.npmjs.com/
https://docs.npmjs.com/misc/semver
https://docs.npmjs.com/getting-started/semantic-versioning
https://semver.org/