Node.js 교재 · 5편 · npm 과 의존성

npm과 package.json — 의존성 관리의 기본

패키지 한 줄로 설치, 버전 범위로 안전하게, lockfile 로 팀과 같은 결과.

npm 패키지가 의존성 트리로 쌓이는 컨셉 아이소메트릭 일러스트

지금까지 Node 본체로만 코드를 짰다. 하지만 실전에선 거의 한 줄도 라이브러리 없이 못 쓴다. 웹 서버 띄울 때 Express, 데이터 검증할 때 Zod, 날짜 다룰 때 date-fns — 다 남이 만든 패키지를 끌어다 쓴다.

그 패키지 카탈로그가 npm registry (260만 개+) 이고, 가져오는 도구가 npm 명령. 그리고 어떤 패키지를 쓰는지 기록하는 파일이 package.json. 이 셋이 Node 프로젝트의 척추다.

1. package.json — 프로젝트의 신분증

새 프로젝트는 빈 폴더에서 npm init -y 한 줄.

$ mkdir my-app && cd my-app $ npm init -y Wrote to /Users/.../my-app/package.json: { "name": "my-app", "version": "1.0.0", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC" }

-y 는 모든 질문에 yes (기본값) 로 답하는 단축. 첫 실습엔 이 모드, 실제 배포할 패키지면 npm init 으로 하나씩 답하는 게 좋다.

핵심 필드 6개만 알면 95% 충분:

필드의미
name패키지 이름. 소문자·하이픈만.
versionSemVer 버전 (major.minor.patch).
type"module" 면 ESM, 생략 시 CommonJS.
main / exports패키지의 진입점 파일.
scriptsnpm run X 로 실행할 단축 명령.
dependencies / devDependencies의존 패키지 목록.

2. 패키지 설치 — install·uninstall·update

가장 자주 쓰는 명령부터.

$ npm install express # 추가 설치 (= npm i express) $ npm install -D vitest # 개발 의존성으로 설치 (devDependencies) $ npm install # package.json 기반 전체 재설치 $ npm uninstall express # 제거 $ npm update # 모든 의존성을 허용 범위 내 최신으로 $ npm outdated # 업데이트 가능한 패키지 목록

설치하면 자동으로 일어나는 3가지:

  • node_modules/ 폴더에 실제 코드 다운로드.
  • package.jsondependencies(또는 devDependencies) 에 한 줄 추가.
  • package-lock.json 에 정확한 버전·해시 기록.
dependencies vs devDependencies — 둘의 차이는 배포 환경에서 설치되는가. Express 처럼 런타임에 필요한 건 dependencies, Vitest 같이 개발할 때만 쓰는 건 -D 플래그로 devDependencies. production 빌드에서 npm install --omit=dev 하면 후자는 제외돼 배포 용량이 작아진다.

3. 버전 범위 — ^·~·정확 버전

package.json 을 보면 버전 앞에 이상한 기호가 붙어 있다.

{ "dependencies": { "express": "^4.21.0", "zod": "~3.23.8", "react": "19.0.0" } }

이 기호가 버전 범위. 의미를 정확히 알아야 안전한 업그레이드가 가능하다.

표기의미예 — express 4.21.0 기준
^4.21.0같은 major 안에서 최신 (가장 흔함)4.21.0 ~ 4.99.99 OK · 5.0.0 X
~4.21.0같은 major.minor 안에서 최신 (보수적)4.21.0 ~ 4.21.99 OK · 4.22.0 X
4.21.0정확히 그 버전만4.21.0 만
*아무 버전 (위험, 비추)모든 버전

현실 권장 — 대부분 ^ 그대로 두기. SemVer 약속상 같은 major 안에서는 호환되니까. 핵심 의존성(React 같은 큰 라이브러리)만 정확 버전으로 고정해 깜짝 깨짐을 방지.

4. lockfile — 팀이 정확히 같은 결과를 받는 비밀

package.json 만으로 부족한 이유 — ^4.21.0 은 "4.x 최신" 인데 매일 새 마이너 버전이 나온다. A 가 오늘 설치하면 4.21.5, B 가 내일 설치하면 4.22.0 — 다른 결과.

그래서 npm 은 설치할 때마다 package-lock.json정확한 버전 + 해시를 적어 둔다. 이 파일을 git 에 같이 커밋하면 팀 전원이 같은 버전을 받는다.

$ npm install # package.json 보고 범위 안 최신 설치 + lock 업데이트 $ npm ci # lockfile 그대로 정확 재현 (CI 에서 권장)

두 명령의 차이는 결정적이다. 로컬에서 npm install 은 약간씩 lockfile 을 바꾸지만, CI 에선 npm ci 가 정답 — lockfile 과 실제 설치가 다르면 즉시 에러로 멈춘다.

흔한 실수package-lock.json.gitignore 에 추가하는 것. 절대 금지. 이 파일이 없으면 매번 다른 버전이 깔려 "내 컴퓨터에선 되는데요" 의 원흉이 된다. 단, 라이브러리 배포 패키지는 lockfile 을 git 에 넣지 않는 것도 한 선택지 (사용자가 자기 lock 을 만들어야 하니까).

5. scripts — 명령어 별칭 모음

package.jsonscripts프로젝트 단축 명령 사전이다.

{ "scripts": { "dev": "node --watch server.js", "start": "node server.js", "test": "vitest", "lint": "eslint .", "build": "tsc", "format": "prettier --write ." } }

실행은 npm run X. 예외로 start·testrun 생략 가능 (npm start·npm test).

장점 두 가지 — ① 팀원이 명령을 외울 필요 없음 (모두가 npm run dev), ② OS 차이를 흡수. 윈도우와 맥의 경로 구분자 차이를 cross-env 같은 패키지로 한 줄에 처리.

요약 — 5편 좌표

여기까지 정리. package.json 은 프로젝트 신분증, npm install 로 패키지 추가하면 자동으로 node_modules/·dependencies·package-lock.json 셋이 갱신. 버전 기호는 ^(같은 major) 가 표준, lockfile 은 반드시 git 커밋. scripts 에 자주 쓰는 명령을 단축어로 박아두면 팀 협업이 매끄럽다. 다음 편에서 진짜 작업 시작 — fs 모듈로 파일 읽기·쓰기.

다음 편 예고 — fs 모듈 파일 다루기

동기 vs 비동기 파일 I/O, 자주 쓰는 메서드. 6편.

© 2026 주나이테크(주) @JUNAITECH