<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Git on kastori</title><link>http://blog.kastori.dev/tags/git/</link><description>Recent content in Git on kastori</description><generator>Hugo -- gohugo.io</generator><language>ko-kr</language><lastBuildDate>Thu, 11 Jun 2026 00:00:00 +0900</lastBuildDate><atom:link href="http://blog.kastori.dev/tags/git/index.xml" rel="self" type="application/rss+xml"/><item><title>알아두면 구하는 Git 명령어 — rebase, squash, cherry-pick, stash, revert</title><link>http://blog.kastori.dev/tech/2026-06-11-git-05-advanced-commands/</link><pubDate>Thu, 11 Jun 2026 00:00:00 +0900</pubDate><guid>http://blog.kastori.dev/tech/2026-06-11-git-05-advanced-commands/</guid><description>&lt;h2 id="언제-이-명령어들이-필요한가"&gt;&lt;a href="#%ec%96%b8%ec%a0%9c-%ec%9d%b4-%eb%aa%85%eb%a0%b9%ec%96%b4%eb%93%a4%ec%9d%b4-%ed%95%84%ec%9a%94%ed%95%9c%ea%b0%80" class="header-anchor"&gt;&lt;/a&gt;언제 이 명령어들이 필요한가
&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;#34;PR 전에 WIP 커밋 5개를 하나로 합치고 싶다&amp;#34; → squash
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;#34;main이 업데이트됐는데 내 브랜치에 깔끔하게 반영하고 싶다&amp;#34; → rebase
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;#34;hotfix 커밋을 다른 브랜치에도 적용하고 싶다&amp;#34; → cherry-pick
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;#34;작업 중인데 급하게 다른 브랜치로 가야 한다&amp;#34; → stash
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;#34;push한 커밋을 이력을 남기며 취소하고 싶다&amp;#34; → revert
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;#34;실수로 커밋을 날렸다&amp;#34; → reflog
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="rebase--커밋-히스토리-재배치"&gt;&lt;a href="#rebase--%ec%bb%a4%eb%b0%8b-%ed%9e%88%ec%8a%a4%ed%86%a0%eb%a6%ac-%ec%9e%ac%eb%b0%b0%ec%b9%98" class="header-anchor"&gt;&lt;/a&gt;rebase — 커밋 히스토리 재배치
&lt;/h2&gt;&lt;h3 id="merge-vs-rebase"&gt;&lt;a href="#merge-vs-rebase" class="header-anchor"&gt;&lt;/a&gt;merge vs rebase
&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;상황: main에 새 커밋이 생긴 동안 feature 브랜치에서 작업
&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;merge 결과 (머지 커밋 생성):
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; main: A → B → C → M
&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; feature: D → E
&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;rebase 결과 (feature를 main 위로 재배치):
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; main: A → B → C → D&amp;#39; → E&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;rebase는 히스토리가 선형으로 유지된다. PR 전에 main의 최신 상태를 반영할 때 유용하다.&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;git checkout feature/login-api
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git rebase main
&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;&lt;span class="c1"&gt;# 1. 충돌 파일 수정&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 2. git add &amp;lt;파일&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 3. git rebase --continue&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 취소: git rebase --abort&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 &lt;blockquote&gt;
 &lt;p&gt;&lt;strong&gt;주의&lt;/strong&gt;: rebase는 커밋 해시가 바뀐다. 팀원과 공유 중인 브랜치에는 절대 쓰지 않는다. 자신의 feature 브랜치에서만.&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="interactive-rebase--커밋-편집"&gt;&lt;a href="#interactive-rebase--%ec%bb%a4%eb%b0%8b-%ed%8e%b8%ec%a7%91" class="header-anchor"&gt;&lt;/a&gt;Interactive Rebase — 커밋 편집
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;git rebase -i&lt;/code&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;# 최근 3개 커밋 편집&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;/code&gt;&lt;/pre&gt;&lt;/div&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;pick a1b2c3 WIP: 로그인 API 작업 중
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pick d4e5f6 WIP: 유효성 검증 추가
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pick g7h8i9 feat(auth): 로그인 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;# 명령어:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# pick → 그대로 유지
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# squash → 이전 커밋과 합치기 (커밋 메시지 편집 가능)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# fixup → 이전 커밋과 합치기 (메시지는 이전 것 유지)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# drop → 커밋 삭제
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# reword → 커밋 메시지만 수정
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;WIP 커밋들을 squash로 정리:&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;pick a1b2c3 WIP: 로그인 API 작업 중
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;squash d4e5f6 WIP: 유효성 검증 추가
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;squash g7h8i9 feat(auth): 로그인 API 완성
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;저장하면 세 커밋이 하나로 합쳐지고 메시지를 새로 작성할 수 있다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="cherry-pick--특정-커밋만-가져오기"&gt;&lt;a href="#cherry-pick--%ed%8a%b9%ec%a0%95-%ec%bb%a4%eb%b0%8b%eb%a7%8c-%ea%b0%80%ec%a0%b8%ec%98%a4%ea%b8%b0" class="header-anchor"&gt;&lt;/a&gt;cherry-pick — 특정 커밋만 가져오기
&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;# 커밋 해시 확인&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git log --oneline feature/payment
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# a1b2c3 feat(payment): 카드 결제 핵심 로직&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 cherry-pick a1b2c3
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&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-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;hotfix를 main에 적용했는데 develop에도 반영해야 할 때
&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;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 cherry-pick a1b2c3 d4e5f6
&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 cherry-pick a1b2c3..g7h8i9
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 &lt;blockquote&gt;
 &lt;p&gt;cherry-pick은 커밋을 &lt;strong&gt;복사&lt;/strong&gt;하는 것. 원본 브랜치에도 커밋이 그대로 남는다.&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="stash--작업-중간에-브랜치-전환"&gt;&lt;a href="#stash--%ec%9e%91%ec%97%85-%ec%a4%91%ea%b0%84%ec%97%90-%eb%b8%8c%eb%9e%9c%ec%b9%98-%ec%a0%84%ed%99%98" class="header-anchor"&gt;&lt;/a&gt;stash — 작업 중간에 브랜치 전환
&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;&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 stash
&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 stash pop &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 stash apply &lt;span class="c1"&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;# stash 목록 확인&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git stash list
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# stash@{0}: WIP on feature/login: ...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# stash@{1}: WIP on feature/payment: ...&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;# 특정 stash 적용&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git stash apply stash@&lt;span class="o"&gt;{&lt;/span&gt;1&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="reflog--실수-복구의-안전망"&gt;&lt;a href="#reflog--%ec%8b%a4%ec%88%98-%eb%b3%b5%ea%b5%ac%ec%9d%98-%ec%95%88%ec%a0%84%eb%a7%9d" class="header-anchor"&gt;&lt;/a&gt;reflog — 실수 복구의 안전망
&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;# 실수로 커밋을 날렸다&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git reset --hard HEAD~3 &lt;span class="c1"&gt;# 최근 3개 커밋 삭제&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;# reflog로 삭제 전 상태 찾기&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git reflog
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# a1b2c3 HEAD@{0}: reset: moving to HEAD~3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# d4e5f6 HEAD@{1}: commit: feat: 주문 API 추가 ← 이걸 살려야 함&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# g7h8i9 HEAD@{2}: commit: feat: 상품 조회 API&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 reset --hard d4e5f6
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;reflog&lt;/code&gt;는 로컬 Git의 모든 HEAD 이동 기록이다. &lt;code&gt;git push&lt;/code&gt;한 후가 아니라면 대부분의 실수를 복구할 수 있다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="reset-정리"&gt;&lt;a href="#reset-%ec%a0%95%eb%a6%ac" class="header-anchor"&gt;&lt;/a&gt;reset 정리
&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 reset --soft HEAD~1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; → 커밋만 취소. 변경사항은 staged 상태로 남음.
&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;git reset --mixed HEAD~1 &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; → 커밋 취소. 변경사항은 unstaged 상태.
&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;git reset --hard HEAD~1
&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="revert--이력을-남기며-되돌리기"&gt;&lt;a href="#revert--%ec%9d%b4%eb%a0%a5%ec%9d%84-%eb%82%a8%ea%b8%b0%eb%a9%b0-%eb%90%98%eb%8f%8c%eb%a6%ac%ea%b8%b0" class="header-anchor"&gt;&lt;/a&gt;revert — 이력을 남기며 되돌리기
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;reset&lt;/code&gt;은 커밋을 삭제하지만 &lt;code&gt;revert&lt;/code&gt;는 &lt;strong&gt;되돌리는 새 커밋을 만든다&lt;/strong&gt;. 이미 push한 브랜치에서는 revert가 안전하다.&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 revert a1b2c3
&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 revert a1b2c3 d4e5f6
&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 revert --no-edit a1b2c3
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;reset vs revert 선택 기준:&lt;/strong&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;reset → 로컬에서만 작업 중, 아직 push 안 함
&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;revert → 이미 push했거나 팀과 공유 중인 브랜치
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#34;이 커밋을 취소했다&amp;#34;는 이력을 남겨야 한다
&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;git log --oneline
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# f1a2b3 feat: 결제 모듈 배포 ← 이게 문제&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;git revert f1a2b3
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# → &amp;#34;Revert &amp;#39;feat: 결제 모듈 배포&amp;#39;&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
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;이력에 revert 커밋이 남기 때문에 &amp;ldquo;언제 왜 롤백했는지&amp;quot;가 추적된다.&lt;/p&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;이 시리즈에서 다룬 것들:&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;#1 브랜칭 전략 → 팀이 브랜치를 어떻게 운영할지
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;#2 커밋 컨벤션 → 변경 이력을 어떻게 기록할지
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;#3 PR &amp;amp; 코드리뷰 → 변경을 어떻게 검토하고 합칠지
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;#4 릴리즈 관리 → 버전을 어떻게 관리하고 배포할지
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;#5 고급 명령어 → 실무에서 마주치는 상황별 도구
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;혼자 프로젝트를 할 때도 이 흐름을 연습해두면, 팀에 합류했을 때 코드보다 협업 방식을 배우는 데 시간을 쓰지 않아도 된다.&lt;/p&gt;</description></item><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>PR을 잘 쓴다는 것 — 작성자와 리뷰어가 모두 편한 코드 리뷰</title><link>http://blog.kastori.dev/tech/2026-06-08-git-03-pull-request/</link><pubDate>Mon, 08 Jun 2026 00:00:00 +0900</pubDate><guid>http://blog.kastori.dev/tech/2026-06-08-git-03-pull-request/</guid><description>&lt;h2 id="리뷰어의-입장에서-생각하기"&gt;&lt;a href="#%eb%a6%ac%eb%b7%b0%ec%96%b4%ec%9d%98-%ec%9e%85%ec%9e%a5%ec%97%90%ec%84%9c-%ec%83%9d%ea%b0%81%ed%95%98%ea%b8%b0" class="header-anchor"&gt;&lt;/a&gt;리뷰어의 입장에서 생각하기
&lt;/h2&gt;&lt;p&gt;PR을 올리고 &amp;ldquo;리뷰 부탁드립니다&amp;quot;를 남긴다. 리뷰어는 맥락 없이 diff만 본다. &amp;ldquo;이게 왜 바뀐 거지?&amp;rdquo;, &amp;ldquo;뭘 테스트해야 하지?&amp;rdquo;, &amp;ldquo;어디서 실행해볼 수 있지?&amp;rdquo; — 이 질문들이 드는 PR은 리뷰 시간이 3배가 된다.&lt;/p&gt;
&lt;p&gt;좋은 PR은 리뷰어의 이 질문들을 미리 답해놓은 문서다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="pr-크기--작을수록-좋다"&gt;&lt;a href="#pr-%ed%81%ac%ea%b8%b0--%ec%9e%91%ec%9d%84%ec%88%98%eb%a1%9d-%ec%a2%8b%eb%8b%a4" class="header-anchor"&gt;&lt;/a&gt;PR 크기 — 작을수록 좋다
&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;✅ 이상적인 PR
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - 변경 파일 5~10개 이하
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - 변경 라인 400줄 이하
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - 하나의 목적 (기능 1개, 버그 1개)
&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;❌ 피해야 할 PR
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - &amp;#34;기능 A + 리팩터링 + 의존성 업그레이드&amp;#34; 한 번에
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - 1,000줄 넘는 PR → 리뷰어가 세부 사항을 놓침
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&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-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;PR 1: Entity + Repository 추가
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;PR 2: Service 로직 구현
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;PR 3: Controller + API 엔드포인트
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;PR 4: 테스트 코드
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;각 PR이 독립적으로 리뷰·머지 가능하도록 설계하면 리뷰 속도가 빨라진다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="pr-본문--리뷰어가-필요한-정보를-모두-담는다"&gt;&lt;a href="#pr-%eb%b3%b8%eb%ac%b8--%eb%a6%ac%eb%b7%b0%ec%96%b4%ea%b0%80-%ed%95%84%ec%9a%94%ed%95%9c-%ec%a0%95%eb%b3%b4%eb%a5%bc-%eb%aa%a8%eb%91%90-%eb%8b%b4%eb%8a%94%eb%8b%a4" class="header-anchor"&gt;&lt;/a&gt;PR 본문 — 리뷰어가 필요한 정보를 모두 담는다
&lt;/h2&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="gu"&gt;## 변경 사항
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&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;&lt;span class="gu"&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;## 주요 변경 파일
&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="sb"&gt;`OAuthController.java`&lt;/span&gt; — OAuth2 콜백 처리
&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="sb"&gt;`OAuth2UserService.java`&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="sb"&gt;`SecurityConfig.java`&lt;/span&gt; — 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 class="gu"&gt;## 테스트 방법
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;1.&lt;/span&gt; 로컬 실행 후 &lt;span class="sb"&gt;`/oauth2/authorization/google`&lt;/span&gt; 접속
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;2.&lt;/span&gt; Google 계정으로 로그인
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;3.&lt;/span&gt; 리다이렉트 후 JWT 토큰 발급 확인
&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;## 관련 이슈
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Closes &lt;span class="ni"&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="코드-리뷰--리뷰어-가이드"&gt;&lt;a href="#%ec%bd%94%eb%93%9c-%eb%a6%ac%eb%b7%b0--%eb%a6%ac%eb%b7%b0%ec%96%b4-%ea%b0%80%ec%9d%b4%eb%93%9c" class="header-anchor"&gt;&lt;/a&gt;코드 리뷰 — 리뷰어 가이드
&lt;/h2&gt;&lt;h3 id="코멘트-레이블"&gt;&lt;a href="#%ec%bd%94%eb%a9%98%ed%8a%b8-%eb%a0%88%ec%9d%b4%eb%b8%94" class="header-anchor"&gt;&lt;/a&gt;코멘트 레이블
&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;[MUST] → 반드시 수정 필요. 머지 전 해결.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 예: &amp;#34;NPE 발생 가능 [MUST]&amp;#34;
&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;[SHOULD] → 수정을 강하게 권장. 이유 설명.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 예: &amp;#34;이 로직은 Service로 옮기는 게 좋을 것 같습니다 [SHOULD]&amp;#34;
&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;[OPINION] → 개인 의견. 수정 강제 아님.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 예: &amp;#34;저라면 메서드명을 ~로 했을 것 같아요 [OPINION]&amp;#34;
&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;[QUESTION] → 이해를 위한 질문. 비판 아님.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 예: &amp;#34;여기서 왜 synchronized를 쓰셨나요? [QUESTION]&amp;#34;
&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;[PRAISE] → 잘한 부분 칭찬.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 예: &amp;#34;이 패턴 깔끔하네요! [PRAISE]&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="리뷰-에티켓"&gt;&lt;a href="#%eb%a6%ac%eb%b7%b0-%ec%97%90%ed%8b%b0%ec%bc%93" class="header-anchor"&gt;&lt;/a&gt;리뷰 에티켓
&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;✅ 코드를 비판하지 말고 개선을 제안한다
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#34;이건 잘못됐어요&amp;#34; → &amp;#34;이렇게 하면 더 나을 것 같습니다&amp;#34;
&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; &amp;#34;왜 이렇게 했나요?&amp;#34; → &amp;#34;이렇게 한 이유가 있으신가요?&amp;#34;
&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; 좋은 코드를 보면 [PRAISE]로 표현
&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;✅ 24시간 이내에 리뷰한다
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 리뷰가 밀리면 PR 작성자의 컨텍스트도 날아간다
&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%a8%b8%ec%a7%80-%ec%a0%84%eb%9e%b5" class="header-anchor"&gt;&lt;/a&gt;머지 전략
&lt;/h2&gt;&lt;p&gt;GitHub에서 PR 머지 시 세 가지 방법을 제공한다.&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;Merge commit
&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; → Git Flow에 적합
&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;Squash and merge
&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; → 커밋 히스토리 깔끔. GitHub Flow에 적합
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; → WIP 커밋이 많아도 괜찮음
&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;Rebase and merge
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; → 브랜치 커밋들을 main 위로 rebase 후 머지
&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;/p&gt;
&lt;hr&gt;
&lt;h2 id="draft-pr-활용"&gt;&lt;a href="#draft-pr-%ed%99%9c%ec%9a%a9" class="header-anchor"&gt;&lt;/a&gt;Draft PR 활용
&lt;/h2&gt;&lt;p&gt;완성되지 않았지만 피드백을 받고 싶을 때는 Draft PR로 올린다.&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;PR 생성 시 &amp;#34;Create draft pull request&amp;#34; 선택
&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;→ 완료되면 &amp;#34;Ready for review&amp;#34;로 전환
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&amp;ldquo;WIP:&amp;rdquo;, &amp;ldquo;DO NOT MERGE&amp;rdquo; 같은 제목 접두사 대신 Draft PR을 쓰는 게 GitHub 표준이다.&lt;/p&gt;
&lt;p&gt;다음 편에서는 PR이 머지된 후 릴리즈를 어떻게 관리하는지 다룬다.&lt;/p&gt;</description></item><item><title>Git + Jira — 브랜치·커밋·PR에 이슈 키 연결하기</title><link>http://blog.kastori.dev/tech/2026-06-07-jira-02-git-integration/</link><pubDate>Sun, 07 Jun 2026 00:00:00 +0900</pubDate><guid>http://blog.kastori.dev/tech/2026-06-07-jira-02-git-integration/</guid><description>&lt;h2 id="코드-변경에-이유를-남기는-방법"&gt;&lt;a href="#%ec%bd%94%eb%93%9c-%eb%b3%80%ea%b2%bd%ec%97%90-%ec%9d%b4%ec%9c%a0%eb%a5%bc-%eb%82%a8%ea%b8%b0%eb%8a%94-%eb%b0%a9%eb%b2%95" class="header-anchor"&gt;&lt;/a&gt;코드 변경에 이유를 남기는 방법
&lt;/h2&gt;&lt;p&gt;6개월 전에 작성한 코드를 보면서 &amp;ldquo;이게 왜 있지?&amp;ldquo;를 되묻는 경험이 있다면, 이 글이 그 문제를 해결해 준다.&lt;/p&gt;
&lt;p&gt;Git 커밋 메시지와 Jira 이슈를 연결하면 코드 한 줄이 어떤 맥락에서 생겼는지 항상 추적할 수 있다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="연동의-핵심-이슈-키"&gt;&lt;a href="#%ec%97%b0%eb%8f%99%ec%9d%98-%ed%95%b5%ec%8b%ac-%ec%9d%b4%ec%8a%88-%ed%82%a4" class="header-anchor"&gt;&lt;/a&gt;연동의 핵심: 이슈 키
&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-fallback" data-lang="fallback"&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;예) BLOG-42
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;이 키를 브랜치명, 커밋 메시지, PR 어디에든 넣으면 Jira가 자동으로 해당 이슈와 연결한다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="브랜치-네이밍"&gt;&lt;a href="#%eb%b8%8c%eb%9e%9c%ec%b9%98-%eb%84%a4%ec%9d%b4%eb%b0%8d" class="header-anchor"&gt;&lt;/a&gt;브랜치 네이밍
&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 switch -c feature/BLOG-42-add-comment-api
&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-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;패턴: {type}/{이슈키}-{설명}
&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;feature/BLOG-42-add-comment-api ← 기능 추가
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;bugfix/BLOG-37-fix-jwt-expiry ← 버그 수정
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;refactor/BLOG-55-split-service ← 리팩터링
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;이슈 키가 앞에 있으면 브랜치 목록에서 어떤 이슈와 연결됐는지 바로 보인다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="커밋-메시지"&gt;&lt;a href="#%ec%bb%a4%eb%b0%8b-%eb%a9%94%ec%8b%9c%ec%a7%80" class="header-anchor"&gt;&lt;/a&gt;커밋 메시지
&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 commit -m &lt;span class="s2"&gt;&amp;#34;feat(comment): 댓글 생성 API 구현 BLOG-42&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;커밋 끝에 이슈 키를 붙이는 것만으로 Jira가 연결을 감지한다.&lt;/p&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;git commit -m &lt;span class="s2"&gt;&amp;#34;feat(comment): 댓글 생성 API 구현
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt;- POST /api/comments 엔드포인트 추가
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt;- 댓글 내용 500자 유효성 검증
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt;BLOG-42&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Smart Commits&lt;/strong&gt; — 커밋 메시지로 Jira 이슈 상태를 자동으로 바꿀 수도 있다.&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;# 작업 시작 시 이슈를 In Progress로&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: 댓글 API 작업 시작 BLOG-42 #in-progress&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;# 완료 시 Done으로&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: 댓글 API 완료 BLOG-42 #done&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="pr-작성"&gt;&lt;a href="#pr-%ec%9e%91%ec%84%b1" class="header-anchor"&gt;&lt;/a&gt;PR 작성
&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;제목: [BLOG-42] feat(comment): 댓글 생성 API 구현
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;PR 본문에는 이슈 링크를 추가한다:&lt;/p&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="gu"&gt;## 관련 이슈
&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; Jira: [&lt;span class="nt"&gt;BLOG-42&lt;/span&gt;](&lt;span class="na"&gt;https://your-domain.atlassian.net/browse/BLOG-42&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; Closes BLOG-42
&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;## 변경 내용
&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; POST /api/comments 엔드포인트 추가
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;-&lt;/span&gt; 댓글 내용 500자 유효성 검증
&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;## 테스트
&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;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;p&gt;&lt;code&gt;Closes BLOG-42&lt;/code&gt;를 적으면 PR이 머지될 때 이슈가 자동으로 Done 처리된다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="github-for-jira-앱-연동"&gt;&lt;a href="#github-for-jira-%ec%95%b1-%ec%97%b0%eb%8f%99" class="header-anchor"&gt;&lt;/a&gt;GitHub for Jira 앱 연동
&lt;/h2&gt;&lt;p&gt;브랜치·커밋·PR이 Jira 이슈 페이지에서 바로 보이려면 앱 연동이 필요하다.&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;1. Jira → Apps → 앱 탐색
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; → &amp;#34;GitHub for Atlassian&amp;#34; (by Atlassian) 설치
&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;2. GitHub 계정 연결
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; → Jira와 다른 구글 계정이어도 무관
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; → 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;3. 연결할 레포 선택 → 승인
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;연동 후 Jira 이슈 페이지:&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;Development 패널:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ├── Branches (1) : feature/BLOG-42-add-comment-api
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ├── Commits (3) : 관련 커밋 목록
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; └── Pull Requests : [Open] 댓글 생성 API
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;이슈 하나에서 관련 코드 변경 전체를 볼 수 있다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="실전-워크플로우-요약"&gt;&lt;a href="#%ec%8b%a4%ec%a0%84-%ec%9b%8c%ed%81%ac%ed%94%8c%eb%a1%9c%ec%9a%b0-%ec%9a%94%ec%95%bd" class="header-anchor"&gt;&lt;/a&gt;실전 워크플로우 요약
&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;1. Jira에서 이슈 생성 → BLOG-42
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2. 브랜치 생성 → feature/BLOG-42-add-comment-api
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;3. 커밋 → &amp;#34;feat: 구현 BLOG-42&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;4. PR → [BLOG-42] feat: 댓글 API / Closes BLOG-42
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;5. 머지 → 이슈 자동 Done
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;혼자 쓸 때는 이 흐름을 다 지키기보다 &lt;strong&gt;브랜치명 + 커밋에 이슈 키&lt;/strong&gt;만 챙겨도 충분하다. 나중에 &lt;code&gt;git log&lt;/code&gt;에서 이슈 키로 검색하면 그 작업의 전체 맥락을 찾을 수 있다.&lt;/p&gt;
&lt;p&gt;다음 편에서는 Slack과 연동해서 Jira + GitHub 알림을 한 곳에 모으는 방법을 다룬다.&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><item><title>팀 Git의 시작 — 브랜칭 전략, Git Flow vs GitHub Flow 언제 뭘 쓰나</title><link>http://blog.kastori.dev/tech/2026-06-04-git-01-branching-strategy/</link><pubDate>Thu, 04 Jun 2026 00:00:00 +0900</pubDate><guid>http://blog.kastori.dev/tech/2026-06-04-git-01-branching-strategy/</guid><description>&lt;h2 id="브랜치-전략이-없으면-생기는-일"&gt;&lt;a href="#%eb%b8%8c%eb%9e%9c%ec%b9%98-%ec%a0%84%eb%9e%b5%ec%9d%b4-%ec%97%86%ec%9c%bc%eb%a9%b4-%ec%83%9d%ea%b8%b0%eb%8a%94-%ec%9d%bc" class="header-anchor"&gt;&lt;/a&gt;브랜치 전략이 없으면 생기는 일
&lt;/h2&gt;&lt;p&gt;main에 직접 push하다가 배포 직전에 미완성 코드가 섞인다. 두 사람이 같은 파일을 수정해서 충돌이 쏟아진다. 버그를 고쳤는데 어디서 배포된 건지 모른다.&lt;/p&gt;
&lt;p&gt;브랜칭 전략은 이런 혼돈을 막는 &lt;strong&gt;팀이 동의한 브랜치 운영 규칙&lt;/strong&gt;이다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="브랜치-역할-이해"&gt;&lt;a href="#%eb%b8%8c%eb%9e%9c%ec%b9%98-%ec%97%ad%ed%95%a0-%ec%9d%b4%ed%95%b4" class="header-anchor"&gt;&lt;/a&gt;브랜치 역할 이해
&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-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;main
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; → 항상 배포 가능한 상태. 직접 push 금지.
&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;feature/xxx
&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; → 완료 후 PR로 main 또는 develop에 머지
&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;hotfix/xxx
&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; → main에서 바로 생성, 수정 후 즉시 배포
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="git-flow--체계적인-릴리즈-관리"&gt;&lt;a href="#git-flow--%ec%b2%b4%ea%b3%84%ec%a0%81%ec%9d%b8-%eb%a6%b4%eb%a6%ac%ec%a6%88-%ea%b4%80%eb%a6%ac" class="header-anchor"&gt;&lt;/a&gt;Git Flow — 체계적인 릴리즈 관리
&lt;/h2&gt;&lt;p&gt;Vincent Driessen이 제안한 전략. 브랜치 종류가 많고 릴리즈 사이클이 명확하다.&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;main ─────────────────────────────── 배포 완료 버전
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ↑ merge ↑ merge
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; release/1.2 hotfix/1.1.1
&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;develop ─────────────────────────── 다음 릴리즈 통합
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ↑ merge ↑ merge
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;feature/login feature/payment
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="흐름"&gt;&lt;a href="#%ed%9d%90%eb%a6%84" class="header-anchor"&gt;&lt;/a&gt;흐름
&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;git checkout develop
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git checkout -b feature/user-auth
&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 develop
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git merge --no-ff feature/user-auth &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 branch -d feature/user-auth
&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 -b release/1.2.0 develop
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 버전 번호 변경, QA 수정&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 merge --no-ff release/1.2.0
&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 1.2.0&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git checkout develop &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; git merge --no-ff release/1.2.0
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="적합한-상황"&gt;&lt;a href="#%ec%a0%81%ed%95%a9%ed%95%9c-%ec%83%81%ed%99%a9" class="header-anchor"&gt;&lt;/a&gt;적합한 상황
&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;✅ 릴리즈 주기가 정해진 서비스 (앱 스토어, 패키지 배포)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;✅ QA 기간이 별도로 필요한 경우
&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="github-flow--단순하고-빠른-배포"&gt;&lt;a href="#github-flow--%eb%8b%a8%ec%88%9c%ed%95%98%ea%b3%a0-%eb%b9%a0%eb%a5%b8-%eb%b0%b0%ed%8f%ac" class="header-anchor"&gt;&lt;/a&gt;GitHub Flow — 단순하고 빠른 배포
&lt;/h2&gt;&lt;p&gt;main 하나 + feature 브랜치. 머지 즉시 배포.&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;main ─────────────────────────── 항상 배포됨
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ↑ PR merge ↑ PR merge
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;feature/login feature/cart
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="흐름-1"&gt;&lt;a href="#%ed%9d%90%eb%a6%84-1" class="header-anchor"&gt;&lt;/a&gt;흐름
&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;# main에서 바로 feature 브랜치 생성&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;git checkout -b feature/add-comment
&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 생성 → 리뷰 → 머지&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 머지 즉시 main으로 배포&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="적합한-상황-1"&gt;&lt;a href="#%ec%a0%81%ed%95%a9%ed%95%9c-%ec%83%81%ed%99%a9-1" class="header-anchor"&gt;&lt;/a&gt;적합한 상황
&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;✅ 웹 서비스, SaaS — 지속적 배포(CD) 환경
&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;❌ 릴리즈 관리가 복잡한 경우
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="trunk-based-development--최소한의-브랜치"&gt;&lt;a href="#trunk-based-development--%ec%b5%9c%ec%86%8c%ed%95%9c%ec%9d%98-%eb%b8%8c%eb%9e%9c%ec%b9%98" class="header-anchor"&gt;&lt;/a&gt;Trunk-based Development — 최소한의 브랜치
&lt;/h2&gt;&lt;p&gt;모든 개발자가 main(trunk)에 직접 또는 짧은 수명의 브랜치로 자주 통합.&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;main ────────────────── 모든 것이 여기로
&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;feature feature feature
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(1~2일 이내 수명)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Feature Flag로 미완성 기능을 숨겨두고 main에 merge한다.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;featureFlags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isEnabled&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;new-payment&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// 새 결제 로직&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// 기존 로직&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&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-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;✅ CI/CD가 완벽히 갖춰진 팀
&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;❌ 테스트 없이 쓰면 main이 자주 깨짐
&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="#%ec%a0%84%eb%9e%b5-%ec%84%a0%ed%83%9d-%ea%b8%b0%ec%a4%80" class="header-anchor"&gt;&lt;/a&gt;전략 선택 기준
&lt;/h2&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;&lt;/th&gt;
 &lt;th&gt;Git Flow&lt;/th&gt;
 &lt;th&gt;GitHub Flow&lt;/th&gt;
 &lt;th&gt;Trunk-based&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;배포 주기&lt;/td&gt;
 &lt;td&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;/td&gt;
 &lt;td&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;CI/CD&lt;/td&gt;
 &lt;td&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;/td&gt;
 &lt;td&gt;높음&lt;/td&gt;
 &lt;td&gt;낮음&lt;/td&gt;
 &lt;td&gt;낮음&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;현실적인 조언&lt;/strong&gt;: 처음 팀에 합류하면 GitHub Flow부터 익히자. 대부분의 스타트업과 웹 서비스 팀이 쓴다. Git Flow는 배포 주기가 정해진 팀에서 만나게 된다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="브랜치-네이밍-컨벤션"&gt;&lt;a href="#%eb%b8%8c%eb%9e%9c%ec%b9%98-%eb%84%a4%ec%9d%b4%eb%b0%8d-%ec%bb%a8%eb%b2%a4%ec%85%98" class="header-anchor"&gt;&lt;/a&gt;브랜치 네이밍 컨벤션
&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-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;feature/PROJ-42-add-login ← 기능 추가
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;bugfix/PROJ-37-fix-jwt ← 버그 수정
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;hotfix/PROJ-61-null-pointer ← 긴급 수정
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;refactor/PROJ-55-split-svc ← 리팩터링
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;chore/PROJ-70-update-deps ← 의존성 등
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;이슈 키를 브랜치명에 포함하면 Jira와 자동 연동된다. 다음 편에서는 커밋 메시지 컨벤션을 다룬다.&lt;/p&gt;</description></item></channel></rss>