NPM 패키지 만들기

1. 필요성

Notion2WordPressTistory2WordPress는 서로 비슷한 코드가 많다.

따라서 별도의 패키지로 만들어서 사용하면 기능을 추가, 수정, 삭제하기 쉽다.

중복되는 기능을 재사용하기 위해서 패키지로 만드는 방법을 배워본다.

오랜만에 생활코딩을 참고했다.

영상이 오래되어 Gemini의 도움도 받았다.


2. 패키지 초기화

npm init
npm init -y # 기본값 사용
Code language: PHP (php)
  • 패키지 초기화
  • package.json 생성

가. Package.json 구성

{
  "name": "@사용자명/패키지-이름",
  "version": "1.0.0",
  "description": "TypeScript 기반의 유틸리티 라이브러리",
  "main": "dist/index.js",
  "types": "dist/index.d.ts",
  "type": "module",
  "scripts": {
    "build": "tsc",
    "start": "node dist/index.js",
    "dev": "ts-node src/index.ts"
  },
  "keywords": ["typescript", "utils"],
  "author": "Your Name",
  "license": "MIT",
  "devDependencies": {
    "typescript": "^5.0.0",
    "ts-node": "^10.9.0",
    "@types/node": "^20.0.0"
  }
}
Code language: JSON / JSON with Comments (json)
항목의미설명
name패키지 이름프로젝트의 고유 명칭. GitHub Registry 사용 시 @사용자명/패키지-이름 필수.
version패키지 버전1.0.0 처럼 Major.Minor.Patch 형식을 따름.
description프로젝트 설명패키지에 대한 짧은 요약. 검색 시 도움을 줌.
type모듈 시스템 결정"module"(ESM) 또는 "commonjs"(CJS) 선택. 현대적 개발엔 "module" 권장.
main진입점 파일다른 프로젝트가 이 패키지를 불러올 때 연결될 핵심 파일 (dist/index.js).
types타입 정의 경로TypeScript 사용자들을 위한 .d.ts 파일의 위치를 지정.
scripts실행 스크립트자주 쓰는 명령어 단축키 (npm run build, npm run dev 등).
dependencies실행용 라이브러리배포 후 실제 프로그램 구동에 꼭 필요한 라이브러리들.
devDependencies개발용 라이브러리빌드 도구, 테스트 도구, TypeScript 컴파일러 등 개발 때만 쓰는 라이브러리.
publishConfig배포 설정어느 레지스트리(GitHub 등)로 배포할지 결정하는 주소 값.
repository저장소 정보소스 코드가 관리되는 Git 저장소 주소.
license라이선스프로젝트 사용 권한 (예: MIT, ISC, UNLICENSED).
binCLI 실행 파일 지정패키지를 전역 설치(npm install -g)했을 때 실행할 명령어와 연결되는 파일을 지정. 예: "my-cli": "dist/cli.js" 형태로 설정하면 터미널에서 my-cli 명령어로 실행 가능.

3. 패키지 배포

npm publish --access public
npm publish --access private
Code language: PHP (php)

다만 npmjs.com에서 Private Package를 사용하면 요금이 발생한다.

따라서 Github Packages를 활용하는 방법도 알아본다.

GitHub Packages를 사용하여 패키지를 배포하는 것은 npmjs.com과 비슷하지만, 인증 방식과 설정 파일(.npmrc)에서 약간의 차이가 있다.


가. Github Personal Access Token

GitHub Packages는 기본적으로 무료 티어에서도 일정 용량까지는 Private 패키지를 제공한다.

GitHub는 보안상 일반 비밀번호 대신 Personal Access Token을 요구한다.

이때 토큰은 write:packages, read:packages, repo 권한이 필요하다.


나. package.json 설정

프로젝트의 package.json 파일에 해당 패키지가 어느 GitHub 저장소에 저장될지 명시해야 한다.

{
  "name": "@사용자명/패키지-이름",
  "version": "1.0.0",
  "publishConfig": {
    "registry": "https://npm.pkg.github.com"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/사용자명/저장소-이름.git"
  }
}
Code language: JSON / JSON with Comments (json)

다. .npmrc 파일 생성 및 인증

@사용자명:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=${YOUR_GITHUB_TOKEN}
Code language: JavaScript (javascript)

프로젝트 루트 디렉토리에 .npmrc 파일을 만들어 GitHub 레지스트리 주소와 인증 토큰을 연결한다.

${YOUR_GITHUB_TOKEN}는 토큰을 직접 넣지 않고 외부에서 환경변수로 제공한다.

# zsh을 사용한다면
echo 'export YOUR_GITHUB_TOKEN="ghp_your_token_here"' >> ~/.zshrc
# 또는 bash를 사용한다면
echo 'export YOUR_GITHUB_TOKEN="ghp_your_token_here"' >> ~/.bashrc
Code language: PHP (php)

YOUR_GITHUB_TOKEN 부분에 아까 생성한 PAT을 넣는다.

만약 직접 토큰을 넣는다면 .gitignore에 추가하여 토큰이 외부에 노출되지 않도록 설정해야 한다!


라. 배포 실행

npm publish

모든 설정이 끝났다면 터미널에서 명령어를 실행한다.


4. 패키지 버전 관리

package.json 파일의 패키지 버전을 직접 수정하지 않고 터미널 명령어로 버전을 올릴 수 있다.

이 명령어를 사용하면 자동으로 package.json 수정, Git commit 및 tag를 생성한다.

npm version patch
# 1.0.0 -> 1.0.1

npm version minor
# 1.0.1 -> 1.1.0

npm version major
# 1.1.0 -> 2.0.0

npm version prerelease --preid=beta
# 1.0.0 -> 1.0.1-beta.0
Code language: PHP (php)
  • patch (0.0.x 올리기): 버그 수정 시
  • minor (0.x.0 올리기): 새로운 기능 추가 시
  • major (x.0.0 올리기): 대규모 변경이나 호환성 깨짐 발생 시

5. 설치하기

@사용자명:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=${YOUR_GITHUB_TOKEN}
Code language: JavaScript (javascript)

Github Registry에서 패키지를 가져와 사용하기 위해선 앞서 생성한 동일한 내용의 .npmrc 파일이 필요하다.

만약 Repo가 Public으로 변경된다면 .npmrc의 토큰 관련 라인은 삭제해도 무방하다.

npm install @사용자명/패키지-이름
Code language: CSS (css)

있다는 가정하에 명령어를 실행한다.

// CommonJS
const myLib = require('@사용자명/패키지-이름');

// ESM (웹 개발 시 주로 사용)
import { myFunction } from '@사용자명/패키지-이름';
Code language: JavaScript (javascript)

설치가 완료되면 node_modules에 추가되며, 일반적인 패키지와 동일하게 불러올 수 있다.

npm outdated
npm update
구분^ (Caret)~ (Tilde)
명칭캐럿틸드
기본 원칙하위 호환성 유지최소한의 변경
범위 (1.0.0 이상)Minor 업데이트 허용Patch 업데이트 허용
범위 (1.0.0 미만)Patch 업데이트 허용Patch 업데이트 허용
주요 용도신규 기능까지 자동으로 업데이트 (npm 기본값)버그 수정 및 보안 패치만 안전하게 수동/자동 업데이트

6. CLI 도구 만들기

다른 애플리케이션에서 라이브러리처럼 사용되는 것이 아니라, 독립 실행형 프로그램으로 CLI에서 직접 실행하려면 아래 절차를 따른다.


가. Shebang 추가

#!/usr/bin/env node
Code language: JavaScript (javascript)

시스템의 PATH에서 node 런타임를 찾아 이 파일을 Node.js 스크립트로 실행하는 Shebang임.

Node.js에서 동작하는 CLI 도구를 개발할 때, 실행 파일의 맨 첫 줄에 반드시 넣어줘야 함.

Shebang을 넣지 않으면, Shell은 해당 파일을 자바스크립트가 아닌 기본 쉘 스크립트(bash나 zsh 등)로 해석하려고 시도함.


나. bin 추가

// package.json
{
	...
  "bin": {
	  "my-cli": "dist/cli.js"
  },
	...
}
Code language: JavaScript (javascript)

package.jsonbin 항목은 해당 패키지를 설치했을 때 터미널에서 바로 실행할 수 있는 명령어(CLI 도구)를 등록하는 설정이다.

npm install -g 명령어로 패키지를 전역으로 설치했을 때 실행할 명령어와 연결되는 파일을 지정할 수 있다.

터미널에서 my-cli 명령어를 입력하면 dist/cli.js를 실행한다.

{
  "name": "my-cli",
  "version": "1.0.0",
  "bin": "./cli.js"
}
Code language: JSON / JSON with Comments (json)

패키지 이름과 명령어 이름이 같을 때 위와 같이 작성할 수도 있다.

이것이 가능한 이유는 bin 항목이 존재한다면 패키지를 설치하면서 node_modules/.bin/ 디렉토리에 실행 파일의 심볼릭 링크(Symbolic Link)를 생성하기 때문이다.

그래서 bin에 등록할 파일(여기선 cli.js)의 맨 첫 줄에는 반드시 Shebang이 포함되어야 한다.


댓글 남기기