리셋 되지 말자

[nodejs 교과서] 5장 패키지 매니저 본문

NodeJS

[nodejs 교과서] 5장 패키지 매니저

kyeongjun-dev 2020. 10. 28. 17:54

npm 로고

간단한 npm 사용법과 npm을 통해 다른 사람이 만들어둔 코드를 사용하는 방법, 자신의 코드를 npm에 배포하여 다른 사람들이 쓸 수 있게 하는 방법을 알아본다.


5.1 npm 알아보기

npm은 Node Package Manager의 약어로, 이름 그대로 노드 패키지 매니저이다. 1.1.2절에서 Node가 JavaScript 프로그램을 컴퓨터에서도 실행할 수 있게 해준다라고 언급했다. 대부분의 JavaScript 프로그램은 패키지라는 이름으로 npm에 등록되어 있으므로 특정 기능을 하는 패키지가 필요하다면  npm에서 찾아 설치하면 된다.

npm에 업로드된 Node 모듈을 패키지라고 부른다. 모듈이 다른 모듈을 사용할 수 있는 것처럼, 패키지가 다른 패키지를 사용할 수도 있다. 이런 관계를 의존 관계라고 부른다. 의존 관계는 다음 절에서 알아본다.

npm의 대체자로 yarn이 있다. 페이스북이 내놓은 패키지 메니저이다. React, React Native 같은 페이스북 진영의 프레임워크를 사용할 때 종종 볼 수 있다. npm과 비교해 편리한 기능이 몇 가지 있지만, 별도로 설치해야 한다.(https://yarnpkg.com) npm 서버가 너무 느릴 경우에는 yarn으로 패키지를 대신 설치할 수 있다.

5.2 package.json으로 패키지 관리하기

설치한 패키지의 버전관리를 package.json이라는 파일로 한다. 노드 프로젝트를 진행하기 위해서 package.json부터 만들고 시작해야 한다.

콘솔에서 프로젝트를 시작할 폴더로 이동한 후, 아래 명령어를 사용하면 된다.

npm init
  • package name: 패키지의 이름이다. package.json의 name 속성에 저장된다.
  • version: 패키지의 버전이다. npm의 버전은 다소 엄격하게 관리된다. 5.3절에서 다룬다.
  • entry point: javaScript 실행 파일 진입점이다. 보통 마지막으로 module.exports를 하는 파일을 지정한다. package.json의 main 속성에 저장된다.
  • test command: 코드를 테스트할 때 입력할 명령어를 의미한다. package.json scripts 속성 안의 test 속성에 저장된다.
  • git repository: 코드를 저장해둔 깃(Git) 저장소 주소를 의미한다. package.json의 repository 속성에 저장된다.
  • keywords: 키워드는 npm 공식 홈페이지(https://npmjs.com)에서 패키지를 쉽게 찾을 수 있도록 해준다. package.json의 keywords 속서에 저장된다.
  • license: 해당 패키지의 라이선스를 넣으면 된다.

npm init 실행을 완료하면 package.json 파일이 생성된다.

{
  "name": "practice",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "cookie": "^0.4.1"
  }
}

 

$ npm run test

> practice@1.0.0 test H:\VSCodeFiles\JS\practice
> echo "Error: no test specified" && exit 1

"Error: no test specified"
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! practice@1.0.0 test: `echo "Error: no test specified" && exit 1`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the practice@1.0.0 test script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     C:\Users\김경준\AppData\Roaming\npm-cache\_logs\2020-10-28T08_01_40_663Z-debug.log

scripts 부분은 npm 명령어를 저장해두는 부분이다. 콘솔에서 npm run [스크립트 명령어]를 입력하면 해당 스크립트가 실행된다. 위처럼 npm run test를 실행하면

"echo \"Error: no test specified\" && exit 1"

이 실행된다.

test 스크립트 외에도 scripts 속성에 명령어 여러 개를 등록해두고 사용할 수 있다. 보통 start 명령어에 node [파일명]을 저장해두고 npm start로 실행한다. start나 test 같은 스크립트는 run을 붙이지 않아도 실행된다.

이제 패키지를 설치해본다.

$ npm install express
npm WARN practice@1.0.0 No description
npm WARN practice@1.0.0 No repository field.

+ express@4.17.1
added 50 packages from 37 contributors and audited 51 packages in 3.202s
found 0 vulnerabilities

WARN은 경고일 뿐이다. ERROR이 에러이다. 해당 경고메시지를 검색하면 해결방법을 찾을 수 있다.

No repository field.
package.json에 repository 속성이 없어서 발생한다. 나중에 소스 코드를 깃허브등의 저장소에 저장한 후, repository 속성을 만들고 깃허브나 깃랩 주소르 적으면 된다.
audited [숫자] packages
패키지를 설치할 때 위의 문장이 출력된다. 이는 패키지에 있을 수 있는 취약점을 자동으로 검사했다는 의미이다.
npm audit은 패키지의 알려진 취약점을 검사할 수 있는 명령어이다. npm에 패키지가 워낙 많다 보니 일부 패키지가 악성 코드를 담고 있는데, 이런 것들이 npm에 보고되고 npm audit을 통해 검사할 수 있다. npm audit fix를 입력하면 npm이 스스로 수정할 수 있는 취약점을 알아서 수정한다. 주기적으로 수정해주자.

패키지를 설치하면 package.json에 dependencies 항목에 추가된다.

  • package.json
{
  "name": "practice",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "cookie": "^0.4.1",
    "express": "^4.17.1"
  }
}

버전 앞에 ^ 표시가 붙어있는데, 다음 절에서 알아보도록 한다.

dependencies에 패키지 이름을 추가하는 옵션이지만 npm@5 부터는 기본값으로 설정되어 있으므로 따로 붙이지 않아도 된다.

추가로 package.json이 있는 디렉토리에 node_modules라는 디렉토리도 생성되었다. 그 안에 설치한 패키지들이 들어있다. 설치된 패키지가 의존하는 패키지들도 설치가 된다.

package-lock.json이라는 파일도 생성되었다. 직접 설치한 express 외에도 node_modules에 들어 있는 패키지들의 정확한 버전과 의존 관계가 담겨 있다. npm으로 패키지를 설치, 수정, 삭제할 때마다 패키지들 간의 내부 의존 관계를 이 파일에 저장한다.

패키지들의 이름을 나열하여 여러 개를 동시에 설치할 수도 있다.

$ npm install morgan cookie-parser express-session
npm WARN practice@1.0.0 No description
npm WARN practice@1.0.0 No repository field.

+ express-session@1.17.1
+ morgan@1.10.0
+ cookie-parser@1.4.5
added 12 packages from 6 contributors and audited 63 packages in 1.328s
found 0 vulnerabilities

개발용 패키지를 설치할 수도 있다. 실제 배포 시에는 사용되지 않고 개발 중에만 사용되는 패키지들이다. npm intall --save-dev [패키지] [...]로 설치한다. --save-dev가 개발용 패키지임을 나타낸다.

개발용 패키지로 nodemon 패키지를 설치한다. 소스 코드가 바뀔 때마다 자동으로 노드를 재실행해주는 패키지이다.

  "dependencies": {
    "cookie": "^0.4.1",
    "cookie-parser": "^1.4.5",
    "express": "^4.17.1",
    "express-session": "^1.17.1",
    "morgan": "^1.10.0"
  },
  "devDependencies": {
    "nodemon": "^2.0.6"
  }
}

package.json에 새로운 항목인 devDependencies가 생긴것을 확인할 수 있다.

npm에는 전역(global) 설치라는 옵션도 있다. 패키지를 현재 폴더의 node_modules에 설치하는 것이 아닌 npm이 설치되어 있는 폴더(환경 변수 경로)에 설치한다. 전역 설치를 했다고 해서 패키지를 모든 곳에서 사용한다는 뜻은 아니다. 대부분 명령어로 사용하기 위해 전역 설치를 한다.

npm install --global [패키지]

 

node_modules 디렉토리를 삭제해도, package.json 파일이 있으면 npm install 명령어를 통해 다시 설치할 수 있다. 즉 node_modules는 보관할 필요가 없다. 그래서 git에 커밋할때도 커밋하지 않는다.

npx
전역 설치한 패키지는 package.json에 기록되지 않는다. 이러한 경우를 위해 npx를 사용한다.
npm install --save-dev rimraf
npx rimraf node_modules
위처럼 rimraf모듈을 package.json의 devDependencies 속성에 기록한 후, 앞에 npx 명령어를 붙여 실행하면 된다. 그러면 패키지를 전역 설치한 것과 같은 효과(명령어로 사용 가능)를 얻을 수 있다. 패키지가 package.json에 기록되어 있으므로 버전 관리도 용이하다.
npm에 등록되지 않은 패키지
모든 패키지가 npm에 등록되어 있는 것은 아니다. 그러한 패키지들은 npm install [저장소 주소] 명령어를 통해 설치할 수 있다.
명령어 줄여쓰기
npm install은 npm i, --save-dev는 -D, npm --gloabal은 global --g로 줄여 쓸수 있다.

5.3 패키지 버전 이해하기

Node 패키지들의 버전은 항상 세 자리로 이루어져 있다. 노드의 버전조차 세 자리다. 버전이 세 자리인 이유는 SemVer 방식의 버전 넘버링을 따르기 때문이다.

SemVer는 Semantic Versioning(유의적 버전)의 약어이다. 버전을 구성하는 세 자리의 숫자가 모두 의미를 가지고 있다는 것을 뜻한다.

첫 번째 자리는 major 버전이다. 0이면 아직 초기 개발 중이라는 뜻이다. 1부터는 정식 버전을 의미한다. major 버전은 하휘 호환이 안 될 정도로 패키지의 내용이 수정되었을 때 올린다. 1.5.0에서 2.0.0으로 올렸다는 것은 1.5.0을 사용하던 사람들이 2.0.0으로 업데이트했을 때 에러가 발생할 확률이 크다는 뜻이다.

두 번째 자리는 minor 버전이다. minor 버전은 하위 호환이 되는 기능 업데이트를 할 때 올린다. 1.5.0을 사용중인 사람이 1.6.0으로 버전을 올리면 아무 문제가 없어야 한다.

세 번째 자리는 patch 버전이다. 새로운 기능이 추가되었다기보다는 기존 기능에 문제가 있어 수정한 것을 내놓았을 때 patch 버전을 올린다. 1.5.0 에서 1.5.1과 같은 형식으로 올린다. 업데이트 후 문제가 없어야 한다.

새 버전을 배포한 후에는 그 버전의 내용을 절대 수정하면 안된다. 수정 사항이 생긴다면 major버전, patch 버전 중 하나를 의미에 맞게 올려서 새로운 버전으로 배포해야 한다.

package.json에는 SemVer식 세 자리 숫자 이외에도 앞에 ^이나 ~ 또는 >, <같은 문자가 붙어 있다. 이 문자는 버전에는 포함되지 않지만 설치하거나 업데이트할 때 어떤 버전을 설치해야 하는지 알린다.

가장 많이 보는 기호는 ^이고, minor 버전까지만 설치하거나 업데이트를 한다. npm i express@^1.1.1이라면 1.1.1 이상부터 2.0.0 미만 버전까지 설치된다. 2.0.0은 설치되지 않는다. 1.x.x와 같이 표현 가능

~ 기호를 사용하면 patch 버전까지만 설치하거나 업데이트한다. npm i express@~1.1.1 이라면 1.1.1 이상부터 1.2.0 미만 버전까지 설치된다. 1.1.x와 같이 표현가능. ~보다 ^이 많이 사용되는 이유는 minor 버전까지는 하위 호환이 보장되기 때문이다.

>, <, >=, <=, =은 알기 쉽게 초과, 미만, 이상, 이하, 동일을 뜻한다. npm i express@>1.1.1처럼 사용한다. 이렇게 사용하면 반드시 1.1.1 버전보다 높은 버전이 설치된다.

@latest도 사용하는데, 안정된 최신 버전의 패키지를 설치한다. x로도 표현할 수 있다. npm i express@latest 또는 npm i express@x

@next를 사용하면 가장 최근 배포판을 사용할 수 있다. @latest와 달리 안정되지 않은 알파나 베타 버전의 패키지를 설치할 수 있다. 알파나 베타버전은 1.1.1-alpha.0나 2.0.0-beta.1처럼 표시한다. 출시 직전의 패키지에는 2.0.0-rc.0처럼 rc(Release Candidate)가 붙는 경우도 있다.


5.4 기타 npm 명령어

npm으로 설치한 패키지를 사용하다 보면 새로운 기능이 추가되거나 버그를 고친 새로운 버전이 나올 때가 있다. npm outdated 명령어로 업데이트할 수 있는 패키지가 있는지 확인해보면 된다.

업데이트를 할 때는 npm update [패키지명]으로 업데이트할 수 있다.

npm uninstall [패키지명]은 해당 패키지를 제거하는 명령어이다. 패키지가 node_modules 디렉토리와 package.json에서 사라진다.

npm search [검색어]로 npm의 패키지를 검색할 수 있다. GUI 환경이라면 (https://npmjs.com)에서 검색. package.json에 넣어둔 keywords가 이때 사용된다.

npm info [패키지명]은 패키지의 세부 정보를 파악하고자 할때 사용하는 명령어이다. package.json의 내용과 의존 관계, 설치 가능한 버전 정보 등이 표시된다.

npm adduser는 npm 로그인을 위한 명령어이다. npm 공식 사이트에서 가입한 계정으로 로그인하면 된다. 나중에 패키지를 배포할 때 로그인이 필요하다. 패키지를 배포하지 않을 것이라면 npm에 가입할 필요는 없다. 가입 방법은 다음 절에서 알아본다.

npm whoami는 로그인한 사용자가 누군지 알려준다. 로그인된 상태가 아니면 에러가 발생한다.

npm logout은 npm adduser로 로그인한 계정을 로그아웃할 때 사용한다.

npm version [버전] 명령어를 사용하면 package.json의 버전을 올린다. 원하는 버전의 숫자를 넣으면 된다. 또는 major, minor, patch라는 문자열을 넣어서 해당 부분의 숫자를 1 올릴 수도 있다.

npm version 5.3.2, npm version minor

 

npm deprecate [패키지명] [버전] [메시지]는 해당 패키지를 설치할 때 경고 메시지를 띄우게 하는 명령어이다. 자신의 패키지에만 이 명령어를 적용할 수 있다. deprecated 처리를 해두면 다른 사용자들이 버그가 있는 버전의 패키지를 설치할 때 경고 메시지가 출력된다.

npm publish는 자신이 만든 패키지를 배포할 때 사용한다. 다음 절에서 사용해본다.

npm unpublish는 배포한 패키지를 제거할 때 사용한다. 24시간 이내에 배포한 패키지만 제거할 수 있다. 이러한 제한이 있는 경우는 패키지의 의존 관계 때문이다.

npm ci는 package.json 대신 package-lock.json에 기반하여 패키지를 설치한다. 

이외에도 명령어가 많이 있는데, npm 공식 문서 (https://docs.npmjs.com/)의 CLI Commands에서 확인할 수 있다.


5.5 패키지 배포하기


5.6 함께 보면 좋은 자료

  • npm 공식 웹 사이트

www.npmjs.com/

  • yarn 공식 웹 사이트

yarnpkg.com/

  • npm 명령어 설명서

docs.npmjs.com/cli/v6/

  • 패키지 간 비교 사이트

npmcompare.com/

  • 패키지 다운로드 추이 확인

npmtrends.com/

  • 패키지명에 네임스페이스 설정하기

docs.npmjs.com/cli/v6/using-npm/scope

Comments