<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Changelog on kastori</title><link>http://blog.kastori.dev/tags/changelog/</link><description>Recent content in Changelog on kastori</description><generator>Hugo -- gohugo.io</generator><language>ko-kr</language><lastBuildDate>Wed, 10 Jun 2026 00:00:00 +0900</lastBuildDate><atom:link href="http://blog.kastori.dev/tags/changelog/index.xml" rel="self" type="application/rss+xml"/><item><title>버전 번호가 약속인 이유 — SemVer, Git Tag, CHANGELOG 관리</title><link>http://blog.kastori.dev/tech/2026-06-10-git-04-release-versioning/</link><pubDate>Wed, 10 Jun 2026 00:00:00 +0900</pubDate><guid>http://blog.kastori.dev/tech/2026-06-10-git-04-release-versioning/</guid><description>&lt;h2 id="버전-번호는-사용자와의-약속이다"&gt;&lt;a href="#%eb%b2%84%ec%a0%84-%eb%b2%88%ed%98%b8%eb%8a%94-%ec%82%ac%ec%9a%a9%ec%9e%90%ec%99%80%ec%9d%98-%ec%95%bd%ec%86%8d%ec%9d%b4%eb%8b%a4" class="header-anchor"&gt;&lt;/a&gt;버전 번호는 사용자와의 약속이다
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;spring-boot-3.2.1&lt;/code&gt;을 쓰고 있다가 &lt;code&gt;3.2.2&lt;/code&gt;로 올릴 때와 &lt;code&gt;4.0.0&lt;/code&gt;으로 올릴 때 대응이 다르다. &lt;code&gt;3.2.2&lt;/code&gt;는 버그 수정이니 그냥 올려도 되지만, &lt;code&gt;4.0.0&lt;/code&gt;은 Breaking Change가 있을 수 있으니 마이그레이션 가이드를 먼저 읽어야 한다.&lt;/p&gt;
&lt;p&gt;이 약속이 **Semantic Versioning(SemVer)**이다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="semantic-versioning"&gt;&lt;a href="#semantic-versioning" class="header-anchor"&gt;&lt;/a&gt;Semantic Versioning
&lt;/h2&gt;&lt;p&gt;형식: &lt;code&gt;MAJOR.MINOR.PATCH&lt;/code&gt; — 예: &lt;code&gt;1.4.2&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;MAJOR → 하위 호환 안 되는 변경 (Breaking Change)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; API 응답 형식 변경, 파라미터 제거
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 사용자가 코드를 수정해야 함
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 예: 1.4.2 → 2.0.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;MINOR → 하위 호환되는 새 기능 추가
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 기존 코드 수정 없이 새 기능 사용 가능
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 예: 1.4.2 → 1.5.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;PATCH → 하위 호환되는 버그 수정
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 예: 1.4.2 → 1.4.3
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="conventional-commits와-연결"&gt;&lt;a href="#conventional-commits%ec%99%80-%ec%97%b0%ea%b2%b0" class="header-anchor"&gt;&lt;/a&gt;Conventional Commits와 연결
&lt;/h3&gt;&lt;p&gt;커밋 타입이 버전에 자동으로 영향을 준다.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;feat: → MINOR 업 (1.4.2 → 1.5.0)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;fix:, perf: → PATCH 업 (1.4.2 → 1.4.3)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docs:, style: 등 → 변화 없음
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;feat!: 또는
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BREAKING CHANGE: → MAJOR 업 (1.4.2 → 2.0.0)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="초기-개발-0xx"&gt;&lt;a href="#%ec%b4%88%ea%b8%b0-%ea%b0%9c%eb%b0%9c-0xx" class="header-anchor"&gt;&lt;/a&gt;초기 개발 (0.x.x)
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;0.1.0 → 아직 안정적이지 않음. 언제든 Breaking Change 가능.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;1.0.0 → 공개 API 확정. 이후부터 SemVer 약속 적용.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="git-tag--버전-번호를-커밋에-붙이기"&gt;&lt;a href="#git-tag--%eb%b2%84%ec%a0%84-%eb%b2%88%ed%98%b8%eb%a5%bc-%ec%bb%a4%eb%b0%8b%ec%97%90-%eb%b6%99%ec%9d%b4%ea%b8%b0" class="header-anchor"&gt;&lt;/a&gt;Git Tag — 버전 번호를 커밋에 붙이기
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 태그 생성 (annotated tag 권장)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git tag -a v1.2.0 -m &lt;span class="s2"&gt;&amp;#34;Release v1.2.0&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 원격에 푸시 (태그는 git push에 포함 안 됨)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git push origin v1.2.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 모든 태그 한 번에 푸시&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git push origin --tags
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 태그 목록 확인&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git tag
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 특정 태그로 체크아웃&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git checkout v1.2.0
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="lightweight-vs-annotated-tag"&gt;&lt;a href="#lightweight-vs-annotated-tag" class="header-anchor"&gt;&lt;/a&gt;lightweight vs annotated tag
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;lightweight tag: git tag v1.2.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; → 단순 포인터. 커밋 해시에 별칭을 붙이는 것.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;annotated tag: git tag -a v1.2.0 -m &amp;#34;메시지&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; → 태그 작성자, 날짜, 메시지, GPG 서명 포함
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; → 릴리즈에는 annotated tag 권장
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="changelog--릴리즈-이력-문서화"&gt;&lt;a href="#changelog--%eb%a6%b4%eb%a6%ac%ec%a6%88-%ec%9d%b4%eb%a0%a5-%eb%ac%b8%ec%84%9c%ed%99%94" class="header-anchor"&gt;&lt;/a&gt;CHANGELOG — 릴리즈 이력 문서화
&lt;/h2&gt;&lt;p&gt;변경 이력을 사람이 읽을 수 있는 형태로 정리한 문서.&lt;/p&gt;
&lt;h3 id="keep-a-changelog-형식"&gt;&lt;a href="#keep-a-changelog-%ed%98%95%ec%8b%9d" class="header-anchor"&gt;&lt;/a&gt;Keep a Changelog 형식
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-markdown" data-lang="markdown"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gh"&gt;# CHANGELOG
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;## [Unreleased]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;## [1.3.0] - 2026-06-04
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;### Added
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;-&lt;/span&gt; Google OAuth2 소셜 로그인 추가 (&lt;span class="ni"&gt;#123&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;-&lt;/span&gt; 주문 취소 API 추가 (&lt;span class="ni"&gt;#124&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;### Fixed
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;-&lt;/span&gt; 로그아웃 후 토큰 무효화 안 되는 버그 수정 (&lt;span class="ni"&gt;#125&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;### Changed
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;-&lt;/span&gt; 회원 API 응답 형식 userId → id 변경
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;## [1.2.1] - 2026-05-20
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;### Fixed
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;-&lt;/span&gt; 주문 목록 페이징 오류 수정
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="자동-생성"&gt;&lt;a href="#%ec%9e%90%eb%8f%99-%ec%83%9d%ec%84%b1" class="header-anchor"&gt;&lt;/a&gt;자동 생성
&lt;/h3&gt;&lt;p&gt;Conventional Commits를 지켰다면 CHANGELOG를 자동으로 생성할 수 있다.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npm install -g conventional-changelog-cli
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;conventional-changelog -p angular -i CHANGELOG.md -s
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="릴리즈-프로세스-github-flow-기준"&gt;&lt;a href="#%eb%a6%b4%eb%a6%ac%ec%a6%88-%ed%94%84%eb%a1%9c%ec%84%b8%ec%8a%a4-github-flow-%ea%b8%b0%ec%a4%80" class="header-anchor"&gt;&lt;/a&gt;릴리즈 프로세스 (GitHub Flow 기준)
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 1. 릴리즈할 main이 준비됐는지 확인&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git checkout main &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; git pull
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 2. 버전 번호 결정 (커밋 내역 기반)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# feat 있으면 MINOR, fix만 있으면 PATCH&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 3. CHANGELOG 업데이트&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;conventional-changelog -p angular -i CHANGELOG.md -s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git add CHANGELOG.md
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git commit -m &lt;span class="s2"&gt;&amp;#34;chore: v1.3.0 릴리즈 노트 업데이트&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 4. 태그 생성 및 푸시&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git tag -a v1.3.0 -m &lt;span class="s2"&gt;&amp;#34;Release v1.3.0&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git push origin main --tags
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 5. GitHub Release 생성 (UI 또는 gh CLI)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gh release create v1.3.0 --notes-from-tag
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="마치며"&gt;&lt;a href="#%eb%a7%88%ec%b9%98%eb%a9%b0" class="header-anchor"&gt;&lt;/a&gt;마치며
&lt;/h2&gt;&lt;p&gt;버전 관리는 &amp;ldquo;배포했다&amp;quot;를 기록하는 것이 아니라 &lt;strong&gt;&amp;ldquo;무엇이 어떻게 바뀌었는가&amp;quot;를 약속하는 것&lt;/strong&gt;이다. SemVer + Conventional Commits + CHANGELOG 세 가지가 맞물리면 릴리즈마다 노트를 수동으로 작성할 필요도 없다.&lt;/p&gt;
&lt;p&gt;다음 편에서는 rebase, squash, cherry-pick 같은 실무 고급 명령어를 다룬다.&lt;/p&gt;</description></item><item><title>커밋 메시지를 잘 쓴다는 것 — Conventional Commits 실전 가이드</title><link>http://blog.kastori.dev/tech/2026-06-06-git-02-commit-convention/</link><pubDate>Sat, 06 Jun 2026 00:00:00 +0900</pubDate><guid>http://blog.kastori.dev/tech/2026-06-06-git-02-commit-convention/</guid><description>&lt;h2 id="git-log에-남는-것들"&gt;&lt;a href="#git-log%ec%97%90-%eb%82%a8%eb%8a%94-%ea%b2%83%eb%93%a4" class="header-anchor"&gt;&lt;/a&gt;git log에 남는 것들
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git log --oneline
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;a3f21c9 수정
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;b12e8f1 fix
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;c94d3a2 asdf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;d77f0e1 작업 완료
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;e23b1c7 ㅁㄴㅇ
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;6개월 전 내가 쓴 커밋들이다. 뭘 고쳤는지, 왜 고쳤는지 전혀 알 수 없다. 커밋 메시지는 코드의 히스토리이고, 미래의 나(또는 동료)에게 보내는 메모다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="conventional-commits-형식"&gt;&lt;a href="#conventional-commits-%ed%98%95%ec%8b%9d" class="header-anchor"&gt;&lt;/a&gt;Conventional Commits 형식
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;type&amp;gt;(&amp;lt;scope&amp;gt;): &amp;lt;subject&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;[optional body]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;[optional footer]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 실제 예시&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;feat&lt;span class="o"&gt;(&lt;/span&gt;auth&lt;span class="o"&gt;)&lt;/span&gt;: Google OAuth2 소셜 로그인 추가
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;기존 이메일/비밀번호 로그인과 병행 사용 가능.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Google Cloud Console에서 OAuth 앱 등록 필요.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Closes &lt;span class="c1"&gt;#123&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="type-종류"&gt;&lt;a href="#type-%ec%a2%85%eb%a5%98" class="header-anchor"&gt;&lt;/a&gt;type 종류
&lt;/h2&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;type&lt;/th&gt;
 &lt;th&gt;언제 쓰나&lt;/th&gt;
 &lt;th&gt;버전 영향&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;feat&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;새 기능 추가&lt;/td&gt;
 &lt;td&gt;Minor ↑&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;fix&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;버그 수정&lt;/td&gt;
 &lt;td&gt;Patch ↑&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;refactor&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;리팩터링 (기능 변화 없음)&lt;/td&gt;
 &lt;td&gt;없음&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;test&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;테스트 추가/수정&lt;/td&gt;
 &lt;td&gt;없음&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;docs&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;문서 변경&lt;/td&gt;
 &lt;td&gt;없음&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;style&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;코드 포맷팅 (로직 무변화)&lt;/td&gt;
 &lt;td&gt;없음&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;chore&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;빌드, 패키지, CI 설정&lt;/td&gt;
 &lt;td&gt;없음&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;perf&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;성능 개선&lt;/td&gt;
 &lt;td&gt;Patch ↑&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="좋은-커밋-메시지의-조건"&gt;&lt;a href="#%ec%a2%8b%ec%9d%80-%ec%bb%a4%eb%b0%8b-%eb%a9%94%ec%8b%9c%ec%a7%80%ec%9d%98-%ec%a1%b0%ea%b1%b4" class="header-anchor"&gt;&lt;/a&gt;좋은 커밋 메시지의 조건
&lt;/h2&gt;&lt;h3 id="제목은-50자-이하-명령형으로"&gt;&lt;a href="#%ec%a0%9c%eb%aa%a9%ec%9d%80-50%ec%9e%90-%ec%9d%b4%ed%95%98-%eb%aa%85%eb%a0%b9%ed%98%95%ec%9c%bc%eb%a1%9c" class="header-anchor"&gt;&lt;/a&gt;제목은 50자 이하, 명령형으로
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ✅ 좋음&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;feat&lt;span class="o"&gt;(&lt;/span&gt;order&lt;span class="o"&gt;)&lt;/span&gt;: 주문 취소 API 추가
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;fix&lt;span class="o"&gt;(&lt;/span&gt;auth&lt;span class="o"&gt;)&lt;/span&gt;: 로그아웃 후 토큰 무효화 안 되는 버그 수정
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ❌ 나쁨&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;feat&lt;span class="o"&gt;(&lt;/span&gt;order&lt;span class="o"&gt;)&lt;/span&gt;: 주문 취소 기능을 구현했습니다 &lt;span class="o"&gt;(&lt;/span&gt;과거형, 너무 김&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;fixed bug &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;type&lt;/span&gt; 없음, 뭘 고쳤는지 모름&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="body는-왜를-설명한다"&gt;&lt;a href="#body%eb%8a%94-%ec%99%9c%eb%a5%bc-%ec%84%a4%eb%aa%85%ed%95%9c%eb%8b%a4" class="header-anchor"&gt;&lt;/a&gt;body는 &amp;ldquo;왜&amp;quot;를 설명한다
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;refactor&lt;span class="o"&gt;(&lt;/span&gt;payment&lt;span class="o"&gt;)&lt;/span&gt;: 결제 전략 패턴으로 분리
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;기존 PaymentService에 &lt;span class="k"&gt;if&lt;/span&gt;/else로 결제 수단이 추가될 때마다
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;코드 수정이 필요했음. 전략 패턴 도입으로 OCP 달성.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;새 결제 수단 추가 시 PaymentStrategy 구현체만 추가하면 됨.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;what(무엇을 바꿨는가)은 코드 diff를 보면 안다. body에는 **why(왜 바꿨는가)**를 쓴다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="breaking-change"&gt;&lt;a href="#breaking-change" class="header-anchor"&gt;&lt;/a&gt;Breaking Change
&lt;/h2&gt;&lt;p&gt;하위 호환성이 깨지는 변경은 반드시 명시한다.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;feat!: 사용자 API 응답 형식 변경
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BREAKING CHANGE: userId 필드가 id로 변경됨.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;기존 클라이언트는 필드명 수정 필요.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;feat!&lt;/code&gt;의 &lt;code&gt;!&lt;/code&gt;가 Breaking Change를 의미한다. SemVer에서 Major 버전 업 트리거.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="커밋-단위-원칙"&gt;&lt;a href="#%ec%bb%a4%eb%b0%8b-%eb%8b%a8%ec%9c%84-%ec%9b%90%ec%b9%99" class="header-anchor"&gt;&lt;/a&gt;커밋 단위 원칙
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;하나의 커밋 = 하나의 목적&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ✅ 좋음 — 목적이 명확한 단위&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git commit -m &lt;span class="s2"&gt;&amp;#34;feat(user): 회원가입 엔티티 추가&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git commit -m &lt;span class="s2"&gt;&amp;#34;feat(user): 회원가입 서비스 로직 구현&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git commit -m &lt;span class="s2"&gt;&amp;#34;feat(user): 회원가입 API 엔드포인트 추가&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git commit -m &lt;span class="s2"&gt;&amp;#34;test(user): 회원가입 서비스 단위 테스트&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ❌ 나쁨 — 여러 목적이 섞임&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git commit -m &lt;span class="s2"&gt;&amp;#34;회원가입 기능 구현 및 버그 수정 및 테스트&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="wip-커밋-처리"&gt;&lt;a href="#wip-%ec%bb%a4%eb%b0%8b-%ec%b2%98%eb%a6%ac" class="header-anchor"&gt;&lt;/a&gt;WIP 커밋 처리
&lt;/h2&gt;&lt;p&gt;작업 중간에 저장해야 할 때는 WIP 커밋을 만들고, PR 전에 정리한다.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 작업 중 임시 저장&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git commit -m &lt;span class="s2"&gt;&amp;#34;WIP: 결제 API 작업 중&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# PR 전에 squash로 깔끔하게 정리&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git rebase -i HEAD~3
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# WIP 커밋들을 squash해서 하나로 합치기&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;squash는 이 시리즈 마지막 편(고급 명령어)에서 다룬다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="changelog-자동-생성"&gt;&lt;a href="#changelog-%ec%9e%90%eb%8f%99-%ec%83%9d%ec%84%b1" class="header-anchor"&gt;&lt;/a&gt;CHANGELOG 자동 생성
&lt;/h2&gt;&lt;p&gt;Conventional Commits 형식을 지키면 CHANGELOG를 자동 생성할 수 있다.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# conventional-changelog 설치&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npm install -g conventional-changelog-cli
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# CHANGELOG.md 생성&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;conventional-changelog -p angular -i CHANGELOG.md -s
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-markdown" data-lang="markdown"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gh"&gt;# CHANGELOG
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;## [1.3.0] - 2026-06-04
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;### Features
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;-&lt;/span&gt; **auth**: Google OAuth2 소셜 로그인 추가 (&lt;span class="ni"&gt;#123&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;-&lt;/span&gt; **order**: 주문 취소 API 추가 (&lt;span class="ni"&gt;#124&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;### Bug Fixes
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;-&lt;/span&gt; **auth**: 로그아웃 후 토큰 무효화 버그 수정 (&lt;span class="ni"&gt;#125&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;커밋 메시지 하나하나가 릴리즈 노트가 된다. 다음 편에서는 이 커밋들을 담는 PR을 잘 쓰는 법을 다룬다.&lt;/p&gt;</description></item></channel></rss>