npm은 Node Package Manager의 약자로 Node.js의 패키지 관리 도구이다. npm은 아래와 같은 주요 기능과 특징을 갖는다.
패키지 설치: Node.js로 작성된 라이브러리나 프레임워크를 설치할 수 있다. 예를 들면, npm install express 명령어를 통해 Express.js 프레임워크를 설치할 수 있다.
패키지 생성 및 배포: 자신만의 라이브러리나 도구를 만들어 npm 저장소에 배포할 수 있습. 이를 통해 다른 개발자들이 만든 패키지를 사용하거나, 자신의 패키지를 다른 사람에게 제공할 수 있다.
package.json: 이 파일은 Node.js 프로젝트의 메타데이터를 포함하며, 프로젝트의 의존성, 스크립트, 버전 정보 등을 정의힌다. npm은 이 파일을 통해 어떤 패키지가 필요한지, 어떤 명령을 실행해야 하는지 등의 정보를 알 수 있다.
의존성 관리: 프로젝트에서 사용하는 모든 패키지의 의존성을 자동으로 관리한다. npm install 명령을 실행하면 package.json에 나열된 모든 의존성이 설치된다.
글로벌 설치: 특정 패키지를 전역적으로 설치하여 시스템의 어느 곳에서나 명령어로 해당 패키지를 사용할 수 있게 할 수 있다. 예를 들면, npm install -g nodemon을 통해 nodemon을 글로벌로 설치할 수 있다.
버전 관리: package.json과 package-lock.json 파일을 통해 프로젝트의 의존성 패키지의 특정 버전을 지정하거나 업데이트 할 수 있다.
스크립트 실행: package.json의 scripts 섹션을 통해 명령어 스크립트를 정의하고 npm run 명령으로 해당 스크립트를 실행할 수 있다.
npm 저장소: 전 세계의 개발자들이 만든 수 많은 패키지를 찾을 수 있는 중앙 저장소 역할을 한다. npmjs.com에서 패키지 정보를 검색하고 문서를 찾아볼 수 있다.
간단히 말해, npm은 Node.js 생태계의 핵심 부분으로, Node.js 개발자가 거의 모든 프로젝트에서 사용하는 도구이다.
위와 같이 터미널에 npm init -y
를 입력하면 package.json
파일이 생성된다.
{
"name": "node-package-manager",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
axios package를 위와 같이 터미널에 입력해 설치하자.
그러면 package.json
파일의dependencies
에 axios가 추가된다.
{
"name": "node-package-manager",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"axios": "^1.5.0"
}
}
위 모듈을 사용하기 위한 예제 코드
const axios = require('axios');
axios.get('https://naver.com')
.then((response) => {console.log(response)})
.catch((error) => {console.log(error)})
axios라는 패키지 폴더 뿐 만 아니라, 이 패키지가 의존하고 있는 모듈 또한 포함되어 있다.
아래 보는 것과 같이 노드 패키지들의 버전은 세 자리로 되어있다. 이는 세 자리가 모두 의미가 있다는 뜻의 Semantic Versioning
이라고 하며 줄여서 SemVer
이라고도 한다.
버전 번호 MAJOR.MINOR.PATCH가 주어지면 다음을 증가시킨다.
시험판 및 빌드 메타데이터에 대한 추가 레이블은 MAJOR.MINOR.PATCH 형식의 확장으로 사용할 수 있다.
~ (틸드)
와 ^ (캐럿)
은 npm 패키지의 package.json 파일에서 의존성의 버전 범위를 지정할 때 사용하는 특별한 문자이다.
~ 뒤에 지정된 버전과 호환되는 패치 수준의 최신 버전을 허용한다.
^ 뒤에 지정된 버전과 호환되는 마이너 수준의 최신 버전을 허용한다.
0의 주 버전 (예: 0.x.y)의 경우, 캐럿은 패치 수준의 변경만 허용한다.
이러한 규칙 덕분에 패키지 의존성 관리가 더 유연해진다. 개발자들은 의존성을 업데이트할 때, breaking change가 없는 범위 내에서 자동으로 패키지를 업데이트할 수 있게 된다.
package-lock.json은 이 package-lock.json이 생성되는 시점의 의존성 트리(node_modules)에 대한 정보를 가지고 있는 파일을 말한다.
package-lock.json 파일은 Node.js 프로젝트의 의존성 트리에 대한 정확한 정보를 제공하는 역할을 한다. 이 파일을 사용하는 주요 이유는 다음과 같다.
일관성: 프로젝트를 다른 환경 또는 다른 개발자들 사이에서 공유할 때, package-lock.json 파일 덕분에 모든 개발자나 환경이 동일한 의존성 버전을 사용할 수 있다. 이로 인해 "내 컴퓨터에서는 잘 돌아가는데"와 같은 문제를 피할 수 있다.
속도 향상: node_modules를 재생성할 필요가 있을 때 (npm install을 실행할 때), package-lock.json이 있으면 NPM은 이 파일을 바탕으로 의존성 트리를 빠르게 재구축할 수 있다.
보안: package-lock.json은 의존성에 대한 정확한 버전 정보뿐만 아니라 각 패키지의 콘텐츠에 대한 해시도 포함하고 있다. 이로 인해, 악의적인 패키지 버전이 삽입되는 것을 방지할 수 있다.
분석: package-lock.json을 통해 프로젝트의 의존성 트리의 정확한 스냅샷을 얻을 수 있으므로, 어떤 의존성이 어떤 버전으로 설치되었는지, 그리고 그 의존성들 사이의 관계는 어떻게 되는지 쉽게 파악할 수 있다.
자동 생성 및 업데이트: npm install 명령을 사용하여 패키지를 추가, 업데이트, 제거할 때, package-lock.json 파일도 자동으로 업데이트된다. 따라서 개발자가 이 파일을 직접 수정할 필요는 없다.
결론적으로, package-lock.json
은 프로젝트의 의존성 관리를 보다 안정적이고 예측 가능하게 만들어주는 중요한 도구이다.
위와 같이, 이렇게 버전의 범위 안에서 설치가 되면 현재는 1.3.1버전이 설치되지만, lodash의 버전이 업데이트된 상태로 publish가 된 후에, 동일한 package.json파일로 npm install을 실행했을 경우, 원래 버전이 아닌, 새러 업데이트된 버전으로 lodash로 설치가 된다.
이렇게 A는 1.3.1을 사용하고 이 package.json파일을 설치한 다른 사람은 다른 모듈과 버전 충돌이 일어날 수도 있다. 이러한 문제를 해결하기 위해서 package-lock.json을 사용한다.
npm audit
은 Node.js 프로젝트에서 사용하는 패키지의 보안 취약점을 검사하는 npm의 명령이다. 이 도구는 프로젝트의 package-lock.json 파일 또는 npm-shrinkwrap.json 파일에 기술된 의존성 전체 트리를 분석하여 알려진 취약점이 있는 패키지를 찾는다.
npm audit
의 주요 기능 및 특징은 다음과 같다.
자세한 보고서 제공: npm audit을 실행하면, 발견된 취약점의 수준, 패키지 이름, 취약점에 대한 설명, 그리고 가능한 경우 수정 방법에 대한 권장사항 등의 정보를 제공한다.
자동 수정: npm audit fix 명령을 사용하면, 가능한 한 많은 취약점을 자동으로 수정할 수 있다. 이 명령은 안전하게 업그레이드 가능한 패키지를 업그레이드하고, 필요한 경우 일부 패키지를 대체한다.
수동 검토: 일부 취약점은 자동으로 해결할 수 없을 수 있다. 이 경우 npm audit은 문제에 대한 정보와 수동으로 해결할 수 있는 방법을 제공한다.
커스텀 보고서: npm audit은 다양한 출력 옵션을 제공하여, 보고서의 형식을 JSON이나 텍스트 등으로 변경할 수 있다. 이러한 기능은 CI/CD 파이프라인이나 자동화된 보안 스캔에 유용하게 사용될 수 있다.
npm audit
은 개발자가 자신의 프로젝트에서 사용하는 패키지들 사이에 숨겨져 있는 보안 취약점을 감지하고 해결하는 데 도움을 준다. 이러한 취약점은 악의적인 공격자에게 프로젝트나 사용자의 데이터를 위협할 수 있기 때문에, 주기적으로 npm audit을 실행하여 프로젝트의 보안 상태를 확인하고 유지하는 것이 좋다.
패키지를 전역(Global)로 설치하려면 -g flag를 사용하면 된다.
전역으로 설치된 패키지는 디렉터리에 관계없이 작동한다.
nodemin은 디렉토리의 파일 변경이 감지되면 노드 응용 프로그램을 자동으로 다시 시작하여 Node.js기반 응용 프로그램을 개발하는 데 도움이 되는 도구이다.
nodemon은 코드나 개발 방법을 추가로 변경할 필요가 없다. nodemon은 노드의 대체 래퍼이다.
nodemon을 사용하려면 스크립트를 실행할 때 명령줄에서 node라는 단어를 바꾸면 된다.
npm install -g 명령어는 전역(global) 범위로 패키지를 설치한다. 이렇게 전역으로 패키지를 설치할 때 다음과 같은 잠재적 문제점이 발생할 수 있다.
버전 충돌: 다양한 프로젝트가 동일한 전역 패키지의 서로 다른 버전을 필요로 할 수 있다. 한 프로젝트에서 필요로 하는 특정 버전의 패키지를 전역으로 설치하면, 다른 프로젝트에서는 해당 버전과 호환되지 않을 수 있다.
권한 문제: 특히 Linux 및 MacOS와 같은 일부 운영 체제에서 전역 패키지 설치는 관리자 권한을 필요로 할 수 있다. 이로 인해 권한 문제가 발생하거나, 의도치 않은 시스템 변경의 위험이 있다.
의존성 문제: 프로젝트의 의존성을 package.json 파일에 명시적으로 기록하지 않게 된다. 따라서 코드를 다른 환경으로 이동하거나 다른 개발자와 공유할 때 필요한 패키지가 누락될 위험이 있다.
불필요한 패키지: 시간이 지나면 어떤 패키지가 전역으로 설치되었는지 추적하기 어려울 수 있다. 이로 인해 불필요한 패키지가 시스템에 계속 남아있게 되며, 이는 시스템의 정리와 관리를 복잡하게 만들 수 있다.
보안 위험: 전역 패키지는 모든 사용자에게 사용 가능하다. 악의적인 패키지가 전역으로 설치되면 시스템 전체에 보안 위험이 발생할 수 있다.
따라서, 특정 프로젝트에 필요한 패키지는 해당 프로젝트의 디렉토리 내부에서 로컬로 설치하는 것이 좋다. 전역 설치는 일반적으로 CLI 도구나 다양한 프로젝트 간에 공유되는 도구의 경우에만 사용하는 것이 바람직하다.
Yarn은 페이스북, 구글 등 여러 회사에 의해 공동 발표된 프로젝트의 의존성을 관리하는 패키지 매니저이다.
Yarn은 npm의 대안으로 만들어졌으며, npm과 동일한 npm 저장소를 사용한다. 다만, Yarn은 의존성 설치의 속도와 보안성 향상, 더 나은 로컬 캐싱 시스템 등의 몇 가지 특징과 이점으로 주목받았다.
속도: Yarn은 동시에 여러 패키지를 설치할 수 있어, 패키지 설치 속도가 빠르다. npm은 한 패키지를 다 설치하고 다 된 후에 다른 패키지를 순차적으로 설치한다.
보안: Yarn은 설치 전에 패키지의 코드 체크섬을 확인하여, 코드의 무결성을 검증한다.
결정론적 설치: 동일한 yarn.lock 파일과 package.json 파일이 주어지면, Yarn은 어디에서든 동일한 방식으로 의존성을 설치한다. 이는 다양한 환경에서 일관성 있는 설치를 보장한다.
오프라인 모드: 한 번 설치된 패키지는 로컬 캐시에 저장된다. 인터넷 연결이 없는 상황에서도 캐시된 패키지는 오프라인 모드로 재설치할 수 있다.
yarn.lock 파일: Yarn은 의존성의 정확한 버전을 기록하는 yarn.lock 파일을 생성한다. 이 파일은 프로젝트의 의존성 버전에 대한 일관성을 유지하는 데 도움이 된다.
호환성: Yarn은 기존의 npm 저장소와 호환되므로, npm을 사용하는 프로젝트를 쉽게 Yarn으로 전환할 수 있다.
Yarn은 위와 같은 장점들로 많은 개발자들에게 인기를 얻었으며, 현재도 계속해서 발전하고 있다.
npm은 Node.js를 설치할 때 같이 설치해서 따로 설치하지 않아도 되지만, yarn은 따로 설치해야 한다.
npm을 이용해서 yarn을 설치해 줄 수 있다.
npm install -g yarn
npm으로 패키지들을 설치하면 package-lock.json파일을 생성하는 것 처럼 yarn으로 패키지를 설치하면 yarn.lock잠금 파일을 생성하게 된다.
package-lock.json파일에 패키지를 최초 설치할 당시 패키지 버전들이 들어있는 것처럼 yarn.lock에도 최초 패키지 추가 시에 버전이 들어있게 된다.
그래서 yarn.lock파일이 있다면 registry에 패키지의 더 최신 버전이 있어도 yarn install로 패키지를 설치할 때 yarn.lock에 있는 버전을 사용하게 된다.
그래서 패키지 버전 문제를 최소화 할 수 있다.
yarn init
yarn init명령어를 이용해서 package.json파일을 생성할 수 있다.
yarn install
yarn혹은 yarn install로 package.json파일에 명시된 모든 dependencies를 설치할 수 있다
yarn install --force
--force 플래그를 이용해서 강제로 모든 패키지를 추가한다.
yarn add
add 명령으로 패키지를 설치할 수 있다
yarn add [package]
yarn add [package]@[version]
yarn add [package]@[tag]
yarn add --dev
--dev 플래그를 사용해서 devDependencies에 패키지를 추가할 수 있다.
yarn global add (yarn global remove)
전역으로 패캐지를 설치해서 다른 프로젝트에서도 해당 패키지를 이용하려면 global을 이용하면 된다.
yarn global add nodemon
yarn upgrade
yarn upgrade로 모든 의존 패키지(dependencies)를 package.json에 정의한 버전의 범위에서 업데이트 할 수 있다.
그렇지만 모든 패키지를 일괄적으로 업그레이드시키면 호환성이 문제로 conflict가 발생할 수 있다
그래서 아래처럼 하나씩 해줄 수 있다.
$ yarn upgrade axios@^1.1.2
yarn remove
yarn remove를 이용해서 특정 패키지를 제거한다.
이렇게 해서 package.json과 yarn.lock에서 동시에 제거가 된다
yarn run [script]
script에 지정해준 명령어를 이용해서 실행할 수 있다.
패키지 관리를 위해서 yarn과 npm이 두개를 하나의 프로젝트에서 혼합해서 사용하면 패키지 충돌 오류가 날 수 있기 때문에 하나의 프로젝트에는 하나의 패키지 매니저를 정해서 사용하는 것이 좋다!