npm 패키지 관리 완벽 가이드

시맨틱 버저닝

npm 패키지의 버전 관리에서는 세 가지 숫자를 사용하는 시맨틱 버저닝(Semantic Versioning) 방식을 채택하고 있습니다.

  • major: 주요 변경 사항으로 이전 버전과 호환되지 않음
  • minor: 새로운 기능 추가, 이전 버전과 호환됨
  • patch: 버그 수정, 이전 버전과 호환됨

의존성 버전 범위 지정

package.json에서 의존성 버전을 지정할 때는 다양한 연산자를 사용할 수 있습니다.

  • *: 최신 버전과 일치
  • ^: 최근 주 버전范围内的 모든 마이너 버전과 일치. 예를 들어 ^2.3.4는 2.x.x 버전すべてに一致し、3.0.0은 포함하지 않음
  • ~: 최근 마이너 버전范围内的 모든 패치 버전과 일치. 예를 들어 ~2.3.4는 2.3.x 버전すべてに一致し、2.4.0은 포함하지 않음

패키지 진입점

라이브러리를 import로 가져올 때 npm은 module 필드를 우선적으로 찾고, 없으면 main 필드를 사용합니다.

{
  "name": "utilshelper",
  "main": "./dist/index.cjs",
  "module": "./dist/index.js"
}

package-lock 파일

버전 잠금 규칙

package-lock.json에 기록된 의존성 버전이 package.json의 버전 범위와 일치하면 package-lock.json에 고정된 버전이 설치됩니다. 버전 범위와 일치하지 않으면 최신 호환 버전을 설치하고 package-lock.json을 다시 작성합니다.

package-lock 제출 여부

프로젝트 개발 시: lock 파일이 있으면 모든 의존성 버전이 고정되어 매번 동일한 버전이 설치됩니다. 이는 예측 불가능한 의존성 문제를 방지합니다.

라이브러리 개발 시: 기여자가 쉽게 개발 환경을 구성할 수 있도록 devDependencies도 lock 파일에 고정하는 것이 좋습니다.

npm 스크립트 원리

npm run 명령을 실행하면 새로운 Shell 프로세스가 생성됩니다. 이 Shell에서 지정된 스크립트 명령이 실행되며, Shell에서 지원되는 모든 명령(Bash 등)을 사용할 수 있습니다.

npm run으로 생성된 Shell은 현재 디렉터리의 node_modules/.bin 폴더를 PATH 환경 변수에 추가합니다. 스크립트 실행 완료 후 원래 PATH를 복원하므로 npm run으로 등록한 명령을 직접 실행할 수 있습니다.

스크립트 실행 방식

{
  "scripts": {
    "parallel": "npm run task-a & npm run task-b",
    "sequential": "npm run task-a && npm run task-b"
  }
}

ampersand(&)는 병렬 실행, double ampersand(&&)은 순차 실행(앞 작업 성공 시 다음 실행)을 의미합니다. Windows 환경에서는这两种 방식을 지원하지 않으므로, npm-run-all 또는 Concurrently 모듈을 설치하여 해결할 수 있습니다.

npm 단축 명령어

npm add -> npm install
npm create -> npm init

npm 패키지 배포

  1. npm 웹사이트에서 계정 생성
  2. npm login 명령어로 로그인
  3. npm init -y로 프로젝트 초기화 (name, version, main 필드 필수 입력)
  4. 패키지 디렉터리에서 npm publish 실행

npm 환경 변수

npm_package_ 접두사를 통해 스크립트에서 package.json 필드에 접근할 수 있습니다.

{
  "name": "myproject",
  "version": "1.0.0",
  "scripts": {
    "info": "node info.js"
  }
}
// info.js
console.log(process.env.npm_package_name);
console.log(process.env.npm_package_version);

중첩된 필드도 지원됩니다.

console.log(process.env.npm_package_scripts_info);

npm 의존성 구분

  • dependencies: 실행 시 필요한 프로덕션 의존성
  • devDependencies: 개발 시 필요한 의존성

설치 명령어

npm i --save express
npm i --save-dev jest

npm i -S lodash
npm i -D typescript

구분 필요 여부

프로젝트 개발 시: 필수적이지 않음.Webpack/Rollup이 모듈 의존성을 분석할 때 해당 모듈이 dep还是devDep는 중요하지 않으며, node_modules에서 찾을 수 있으면 됨

라이브러리 개발 시: 필수적임. 프로젝트에서 라이브러리를 설치할 때 dependencies만 node_modules에 설치되고 devDependencies는 설치되지 않음. 구분하지 않으면 Consumer 프로젝트에서 오류 발생

npm 라이프사이클 훅

npm은 pre와 post 두 가지 훅을 자동으로 제공합니다. npm run 스크립트 실행 시 자동으로 해당 훅이トリガー됩니다.

{
  "scripts": {
    "prebuild": "echo '빌드 전 작업'",
    "build": "webpack",
    "postbuild": "echo '빌드 후 작업'"
  }
}

npm run build 실행 시: prebuild → build → postbuild 순으로 실행됩니다.

publish, install, uninstall, version, test, stop, start, restart 등의 주요 스크립트도 동일하게 훅을 지원합니다.

npm restart 명령어

npm restart는复合 명령어로, 실제로 세 가지 스크립트를 순차적으로 실행합니다:

prerestart
prestop
stop
poststop
restart
prestart
start
poststart
postrestart

npm publish 라이프사이클

npm publish 실행 시 자동으로 다음 스크립트가 순차 실행됩니다:

prepublishOnly: 패키지 배포 전 필요한 작업 (테스트, 빌드 등) 수행
prepack
prepare
postpack
publish
postpublish

prepare 훅

가장 자주 사용되는 라이프사이클 훅으로, 다음과 같은 타이밍에 실행됩니다:

  • npm install 후 자동 실행
  • npm publish 전 자동 실행

git hook 도구인 husky는 보통 이 훅에서 실행됩니다.

{
  "prepare": "husky install"
}

npm_lifecycle_event 변수

현재 실행 중인 스크립트 이름을 반환하는 환경 변수입니다. 단일 스크립트 파일에서 여러 npm 명령에 대한 로직을 분기 처리할 수 있습니다.

const EVENT = process.env.npm_lifecycle_event;

if (EVENT === 'test') {
  console.log('테스트 작업 실행 중');
}

if (EVENT === 'pretest') {
  console.log('테스트 전 작업 실행 중');
}

if (EVENT === 'posttest') {
  console.log('테스트 후 작업 실행 중');
}

npx 명령어

npm 5.2부터 제공되는 npx는 패키지의 명령줄 도구를 쉽게 실행할 수 있도록 합니다.

로컬 설치 모듈 직접 실행

일반적으로 의존성 설치 후 package.json의 scripts에 등록하고 npm run으로 실행하지만, npx를 사용하면 바로 실행할 수 있습니다.

{
  "scripts": {
    "start": "next start",
    "build": "next build",
    "lint": "next lint"
  }
}

npx next start 명령으로 scripts에 등록 없이 바로 실행 가능합니다.

전역 설치 방지

npx는 의존성을 임시 디렉터리에 다운로드하여 실행 후 삭제합니다.

npx uglify-js@3.0.0 src/app.js -o dist/app.js
npx http-server

다른 버전의 Node.js 사용

npx -p node@14 npm run dev

실행 과정: node@14 다운로드 → 해당 버전으로 전환 → 명령 실행 → 실행 후 삭제 (로컬 버전 불변)

npx 실행 로직

먼저 현재 프로젝트의 node_modules에서 실행 파일을 찾고, 없으면 PATH에서 찾습니다. 그래도 없으면 임시로 설치 후 실행하고 완료되면 삭제합니다.

npm init 명령어

npm init [--force|-f|--yes|-y|--scope]
npm init <@scope>
npm init [<@scope>/]<name>

npm init xxx는 자동으로 npx 명령어로 변환됩니다.

npm init react-app -> npx create-react-app
npm init vue-project -> npx create-vue
npm init @myorg/package -> npx @myorg/create

예를 들어 최신 Vue 프로젝트 생성:

npm init vue@latest -> npx create-vue@latest

npm exec 명령어는 npx와 유사하지만, 뒤따르는 플래그와 옵션을 위치 매개변수로 처리하는 방식이 다릅니다.

npm link 명령어

로컬 npm 패키지를 개발 중인 것처럼 테스트할 수 있도록 심볼릭 링크를 생성합니다. 로컬 프로젝트와 로컬 모듈을 연결하여 수정과 디버깅을方便하게 합니다.

로컬 링크

cd /path/to/project
npm link ../mymodule

프로젝트의 node_modules에 mymodule 심볼릭 링크가 생성됩니다.

전역 링크

1. 전역에 링크 등록:

cd /path/to/mymodule
npm link

전역 node_modules에 심볼릭 링크 생성

2. 프로젝트에서 링크 참조:

cd /path/to/project
npm link mymodule

링크 해제

로컬 링크 해제:

cd /path/to/project
npm unlink mymodule

전역 링크 해제:

cd /path/to/mymodule
npm unlink mymodule

실제 사용 예시

최신 개발 중인 Vite를 테스트하려면:

git clone https://github.com/vitejs/vite.git
cd vite
pnpm install
cd packages/vite
npm run build
npm link
cd /path/to/myproject
pnpm link --global vite
npm run dev

link 후에는 프로젝트에서 vite 명령어를 직접 사용할 수 있습니다.

태그: npm nodejs package-management frontend development-tools

7월 7일 16:51에 게시됨