이 글은 누구를 위한 것인가
- 모노레포에서 여러 패키지의 버전을 일관되게 관리하려는 팀
- npm에 패키지를 배포할 때 CHANGELOG와 버전을 자동화하려는 개발자
- Changesets를 처음 도입하는 팀을 위한 설정 가이드가 필요한 개발자
들어가며
모노레포에서 패키지 버전을 수동으로 관리하면 @myapp/ui v1.2.3이 @myapp/core v2.1.0과 호환되는지 추적하기 어렵다. Changesets는 변경 내역을 파일로 기록하고, 자동으로 버전을 범프하고 CHANGELOG를 생성한다.
이 글은 bluefoxdev.kr의 Changesets 패키지 관리 가이드 를 참고하여 작성했습니다.
1. Changesets 워크플로우
[Changesets 핵심 흐름]
1. 개발자가 PR에서 변경사항 기록:
pnpm changeset
→ .changeset/random-name.md 파일 생성
→ 어떤 패키지가 어떻게 변경됐는지 기록 (patch/minor/major)
2. PR 머지 후 Changesets 봇이 "Version PR" 생성:
→ 모든 changeset 파일을 읽어 버전 범프
→ CHANGELOG.md 업데이트
→ package.json version 업데이트
3. Version PR 머지 시 자동 배포:
→ npm publish 실행
→ GitHub Release 생성
[버전 범프 규칙 (semver)]
patch (1.0.X): 버그 수정, 내부 변경
minor (1.X.0): 하위 호환 새 기능
major (X.0.0): 호환성 깨지는 변경
[Linked Packages]
@myapp/core 변경 시 @myapp/react도 같이 버전업
→ 사용자가 호환성 걱정 없이 설치 가능
2. Changesets 완전 설정
# 1. Changesets 설치
pnpm add -D @changesets/cli -w
# 2. 초기화
pnpm changeset init
# → .changeset/config.json 생성
# 3. 변경 기록 (개발자가 PR마다 실행)
pnpm changeset
# 대화형 CLI:
# - 변경된 패키지 선택
# - major/minor/patch 선택
# - 변경 내용 입력
// .changeset/config.json
{
"$schema": "https://unpkg.com/@changesets/config@3.0.0/schema.json",
"changelog": "@changesets/cli/changelog",
"commit": false,
"fixed": [],
// ui와 react는 항상 같이 버전업
"linked": [["@myapp/ui", "@myapp/react"]],
"access": "public",
"baseBranch": "main",
"updateInternalDependencies": "patch",
"ignore": ["@myapp/docs", "@myapp/examples"] // 배포 제외 패키지
}
// .changeset/cobalt-dogs-dance.md (자동 생성)
---
"@myapp/ui": minor
"@myapp/core": patch
---
Button 컴포넌트에 `loading` props 추가
- `loading` prop으로 로딩 스피너 표시
- @myapp/core의 `useAsync` 훅 버그 수정 (#234)
# .github/workflows/release.yml
name: 릴리스
on:
push:
branches: [main]
concurrency: ${{ github.workflow }}-${{ github.ref }}
jobs:
release:
name: 릴리스
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'pnpm'
registry-url: 'https://registry.npmjs.org'
- run: pnpm install --frozen-lockfile
- name: 빌드
run: pnpm build
- name: Changesets 봇 PR 생성 또는 배포
uses: changesets/action@v1
with:
# PR이 없으면 생성, PR이 머지되면 배포
version: pnpm changeset version
publish: pnpm changeset publish
title: '🚀 버전 업데이트'
commit: '🔖 버전 업데이트'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
// packages/ui/package.json
{
"name": "@myapp/ui",
"version": "1.5.0",
"description": "공유 UI 컴포넌트 라이브러리",
"main": "./dist/index.js",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"exports": {
".": {
"import": "./dist/index.mjs",
"require": "./dist/index.js",
"types": "./dist/index.d.ts"
},
"./button": {
"import": "./dist/button.mjs",
"require": "./dist/button.js"
}
},
"files": ["dist"],
"scripts": {
"build": "tsup src/index.ts --format cjs,esm --dts",
"dev": "tsup src/index.ts --format cjs,esm --dts --watch"
},
"peerDependencies": {
"react": "^18.0.0 || ^19.0.0"
},
"devDependencies": {
"@myapp/tsconfig": "workspace:*"
}
}
// 사전 릴리스 (alpha/beta) 관리
// pnpm changeset pre enter alpha
// → .changeset/pre.json 생성
// → 이후 모든 버전은 1.6.0-alpha.0, 1.6.0-alpha.1, ...
// pnpm changeset pre exit
// → alpha 종료, 다음 버전은 정식 배포
// 특정 패키지만 배포 (emergency fix)
// pnpm changeset publish --filter @myapp/ui
// Turborepo와 통합
// turbo.json
// {
// "pipeline": {
// "build": {
// "dependsOn": ["^build"],
// "outputs": ["dist/**"]
// },
// "publish": {
// "dependsOn": ["build"],
// "cache": false
// }
// }
// }
// 버전 PR 예시 내용 (Changesets가 자동 생성)
// CHANGELOG.md
// ## 1.6.0 - 2026-04-23
//
// ### Minor Changes
// - Button 컴포넌트에 loading props 추가
// (#234, @developer-name)
//
// ### Patch Changes
// - Updated dependencies:
// - @myapp/core@2.3.1
// 내부 패키지 (배포 안 하는 것) 구분
// package.json에 "private": true 추가
// changeset config의 ignore 배열에 추가
마무리
Changesets는 변경 기록을 PR 시점에 개발자가 직접 작성하도록 강제한다. 이 파일이 쌓여 버전 PR이 생성될 때 CHANGELOG가 자동으로 만들어진다. linked 설정으로 관련 패키지의 버전을 동기화하면 사용자는 항상 호환되는 버전 조합을 사용할 수 있다. GitHub Actions와 결합하면 PR 머지 → 버전 PR 자동 생성 → 버전 PR 머지 → npm 배포까지 완전 자동화된다.