npm에 패키지를 배포하고 나서 "아, 이걸 빠뜨렸네"를 겪고 나면 버전을 올려야 한다. 배포 전에 확인할 것들을 한 곳에 정리해둔다.
package.json 핵심 필드
배포에 직접 영향을 주는 필드들이다.
{
"name": "@lukaplayground/my-package",
"version": "1.0.0",
"description": "한 줄 설명",
"type": "module",
"main": "src/index.js",
"bin": {
"my-cmd": "bin/my-cmd.js"
},
"files": [
"bin/",
"src/",
"README.md",
"LICENSE"
],
"engines": {
"node": ">=18.0.0"
},
"keywords": ["keyword1", "keyword2"],
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/username/my-package.git"
}
}
| 필드 | 역할 | 주의사항 |
|---|---|---|
name |
패키지 이름 | scoped(@org/name)면 조직 계정 필요 |
version |
배포 버전 | 한 번 배포한 버전은 덮어쓸 수 없음 |
type |
모듈 시스템 | "module" = ESM, 없으면 CommonJS |
main |
진입점 | require() 또는 import 시 로드되는 파일 |
bin |
CLI 명령어 등록 | npx 또는 글로벌 설치 시 사용 |
files |
배포 포함 파일 | 명시 안 하면 .gitignore 제외 전체 포함 |
engines |
Node.js 최소 버전 | ESM + top-level await는 Node 18 이상 |
files 필드 — 배포 크기의 핵심
files 배열을 명시하지 않으면 .gitignore에 없는 파일이 전부 들어간다. 테스트 파일, 설정 파일, .env.example까지 딸려간다.
"files": [
"bin/",
"src/",
"README.md",
"LICENSE"
]
files 설정과 무관하게 항상 포함되는 파일들이 있다.
package.jsonREADME.md(대소문자 무관)LICENSE(대소문자 무관)main에 지정된 파일
반대로 설정과 무관하게 항상 제외되는 파일들도 있다.
.git/node_modules/.env계열
npm pack — 배포 전 반드시 확인
실제 배포 전에 어떤 파일이 패키지에 들어가는지 확인하는 명령어다.
npm pack --dry-run
--dry-run은 실제 파일을 만들지 않고 목록만 출력한다.
npm notice Tarball Contents
npm notice 1.1kB LICENSE
npm notice 2.3kB README.md
npm notice 1.2kB bin/commitgen.js
npm notice 1.7kB package.json
npm notice 4.2kB src/index.js
npm notice 3.1kB src/commands/configure.js
npm notice 25.6kB package size
npm notice 6.7kB unpacked size확인할 것 두 가지:
- 의도한 파일만 들어갔는가 — 테스트 파일, 설정 파일이 섞여있지 않은지
- 민감한 파일이 빠졌는가 —
.env, API 키, 비밀번호가 포함되지 않았는지
--dry-run 없이 실행하면 .tgz 파일이 생성된다. 직접 압축 풀어서 확인하고 싶을 때 쓴다.
bin 파일 — 실행 권한과 shebang
CLI 도구를 만들 때 bin 파일에 두 가지가 반드시 있어야 한다.
#!/usr/bin/env node
// bin/my-cmd.js
import { run } from '../src/index.js'
run()
#!/usr/bin/env node — 이 한 줄이 없으면 npx로 실행 시 "permission denied" 또는 스크립트가 텍스트로 출력되는 문제가 생긴다.
macOS/Linux에서는 파일 실행 권한도 확인한다.
chmod +x bin/my-cmd.js
Windows는 npm이 자동으로 처리하므로 신경 쓰지 않아도 된다.
ESM vs CommonJS
"type": "module"을 쓰면 .js 파일이 ESM으로 처리된다. 몇 가지 주의사항이 있다.
require()를 쓸 수 없다. import만 사용 가능하다.
// ESM
import { something } from './utils.js'
import fs from 'fs'
// CommonJS (type: module에서는 불가)
const { something } = require('./utils.js')
상대 경로에 확장자를 반드시 붙여야 한다.
// 틀림
import { run } from './src/index'
// 맞음
import { run } from './src/index.js'
__dirname, __filename을 쓸 수 없다. 대신 import.meta.url을 쓴다.
import { fileURLToPath } from 'url'
import { dirname } from 'path'
const __filename = fileURLToPath(import.meta.url)
const __dirname = dirname(__filename)
배포 전 체크리스트
□ node bin/my-cmd.js --version 정상 출력 확인
□ node bin/my-cmd.js --help 명령어 목록 표시 확인
□ npm pack --dry-run 포함 파일 목록 확인
□ .env, API 키가 목록에 없는지 확인
□ .gitignore에 node_modules/, .env 포함 확인
□ files 필드로 배포 범위 제한
□ engines로 Node.js 최소 버전 명시
□ README.md에 설치 방법과 사용법 작성
□ LICENSE 파일 포함
□ bin 파일 상단에 #!/usr/bin/env node 확인
□ 버전 번호 확인 (이전 배포 버전보다 높은지)실제 배포
# npm 로그인 (최초 1회)
npm login
# scoped 패키지는 기본이 private — public으로 배포하려면 플래그 필요
npm publish --access public
# 배포 후 확인
npm info @lukaplayground/my-package
배포 후 72시간 이내에는 npm unpublish로 취소할 수 있다. 이후엔 deprecate만 가능하다.
버전 관리 — semver
# 패치 버전 올리기 (1.0.0 → 1.0.1) — 버그 수정
npm version patch
# 마이너 버전 (1.0.0 → 1.1.0) — 하위 호환 기능 추가
npm version minor
# 메이저 버전 (1.0.0 → 2.0.0) — 하위 호환 깨지는 변경
npm version major
npm version 명령어는 package.json 버전을 올리고 git tag까지 자동으로 만들어준다.
정리
| 단계 | 확인 항목 |
|---|---|
| package.json | files, bin, engines, type 필드 |
| 배포 전 | npm pack --dry-run으로 포함 파일 확인 |
| bin 파일 | #!/usr/bin/env node shebang 확인 |
| ESM | 상대 경로 확장자 .js 필수 |
| 배포 | npm publish --access public (scoped 패키지) |
| 버전 | npm version patch/minor/major |
한 번 배포한 버전은 덮어쓸 수 없다. npm pack --dry-run을 습관으로 만들면 실수가 줄어든다.
'개발 팁' 카테고리의 다른 글
| 풀스택 앱 무료 배포 완전 가이드 — Vercel + Railway + MongoDB Atlas (0) | 2026.02.25 |
|---|---|
| JWT 인증 구현 — Node.js, Python, Go 비교 (0) | 2026.02.25 |
| React + Vite 프로젝트 초기 세팅 — 매번 하는 것들 정리 (0) | 2026.02.25 |
| VSCode 필수 확장 프로그램 추천 - 2026년 실사용 기준 (0) | 2026.01.26 |