긴급 보안 패치가 필요합니다. 그런데 main에는 아직 출시 안 한 기능이 잔뜩 머지돼 있습니다. "패치만 프로덕션에 넣어야 하는데, main을 배포하면 미완성 기능까지 나가요." 팀이 우왕좌왕합니다.
또 다른 팀은 두 달째 사는 feature/redesign 브랜치를 main에 합치려다 충돌 수백 개에 막혔습니다.
브랜치 전략은 '브랜치를 어떻게 따고 합치고 배포하는가'의 팀 규칙입니다. 이게 없거나 안 맞으면, 긴급 상황과 큰 작업에서 반드시 사고가 납니다.
- 1Git Flow·GitHub Flow·Trunk-based의 구조와 차이를 설명할 수 있다
- 2장수 브랜치의 "머지 지옥" 위험과 작은 통합의 가치를 설명할 수 있다
- 3핫픽스·릴리스 브랜치가 긴급 배포에서 하는 역할을 설명할 수 있다
- 4브랜치 전략이 배포 파이프라인(어느 브랜치→어느 환경)과 어떻게 연결되는지 설명할 수 있다
확대
위 그림처럼 Git Flow는 브랜치 역할을 명확히 분리해, 정해진 릴리스 주기와 긴급 패치를 체계적으로 관리합니다.
세 가지 대표 전략
복잡도와 배포 빈도의 트레이드오프
브랜치 전략은 "얼마나 자주 배포하고, 몇 개 버전을 유지하나"에 따라 갈립니다.
확대
- Trunk-based: 작게 자주 통합. CI/CD·자동테스트·기능 플래그가 전제. 빠른 배포에 최적.
- GitHub Flow: 기능 브랜치 → PR → main → 배포. 단순하고 웹 서비스에 무난.
- Git Flow: 역할별 브랜치로 릴리스 주기·다중 버전·QA 게이트를 체계화. 무겁지만 구조적.
핫픽스 — 긴급 패치의 길
미완성과 섞이지 않고 prod만 고치는 경로
오프닝의 "패치만 넣어야 하는데 main엔 미완성 기능이…" 문제는 핫픽스 브랜치로 풉니다.
핫픽스는 현재 prod에 떠 있는 코드(태그 v1.2.0)에서 hotfix/ 브랜치를 따서 패치한 뒤 prod로 배포하고 새 태그(v1.2.1)를 답니다.
- 핵심: 핫픽스는 개발 중인
develop/mainHEAD가 아니라 현재 prod 태그에서 분기한다. - → 미완성 기능을 끌고 가지 않고 긴급 수정만 배포 가능.
Trunk-based에서도 같은 원리로 'prod 태그에서 hotfix 브랜치 → 패치 → 즉시 배포 → main에 백포트'합니다. 핵심은 **"긴급 수정이 미완성 작업과 섞이지 않게 분리"**하는 것 — 이것이 브랜치 전략이 운영 안전에 직결되는 지점입니다.
확대
위 그림처럼 Trunk-based는 하루에도 여러 번 main에 병합해 통합 지옥을 방지하고, Feature Flag로 미완성 기능을 숨깁니다.
어느 브랜치가 어디에 떠 있나 — 직접 확인
배포 사고를 막으려면 "어느 브랜치가 어느 환경에 배포되는가"가 명확해야 합니다. 미머지 브랜치와 환경 매핑을 점검합니다.
# main에 아직 머지 안 된 브랜치들(장수 브랜치 = 머지 지옥 위험)
git branch -a --no-merged main
# 각 브랜치가 main보다 얼마나 뒤처졌나(통합 지연 정도)
git for-each-ref --format='%(refname:short) %(committerdate:relative)' refs/heads/
# 현재 prod에 떠 있는 태그(롤백·핫픽스 기준점)
git tag --sort=-creatordate | head -3
$ git branch --no-merged main
feature/redesign ← 마지막 커밋 2개월 전! 머지 지옥 임박
feature/payment-v2 ← 3일 전, 정상 범위
환경 매핑(팀 규칙 예):
main 머지 → staging 자동 배포
태그 vX.Y.Z → production 배포
hotfix/* → production 직행(승인 후)
git branch -a --no-merged main- --no-merged 목록에 수주~수개월 된 브랜치가 있으면 "머지 지옥" 경고 → 작게 쪼개 자주 통합하도록 개입. 오래될수록 충돌·재테스트 비용 폭증
- 브랜치↔환경 매핑이 문서화돼 있는지 확인 — 없으면 "어느 코드가 prod에 떠 있나"를 아무도 확신 못 함(배포 사고 원인 1순위)
- prod 태그가 명확하면 롤백·핫픽스 기준점이 분명 → 긴급 상황에서 "이 태그로 되돌린다"가 즉시 가능. 태그 없으면 위험
- 기능 플래그 사용 팀이면 "배포됨 ≠ 노출됨" — main에 머지·배포돼도 플래그 OFF면 사용자에겐 안 보임. 릴리스 논의 시 이 구분을 확인
상황: 대규모 리디자인을 feature/redesign 브랜치에서 두 달간 진행한 뒤 main에 머지하려는데, 그사이 main이 수백 커밋 바뀌어 충돌이 폭발하고, 억지로 합친 뒤엔 회귀 버그가 쏟아집니다.
원인: 장수 브랜치(long-lived branch) 가 main과 멀어진 '머지 지옥'입니다. 통합을 미룬 두 달치 차이를 한 번에 합치려니 충돌과 재테스트가 감당 불가가 됐습니다. 통합을 미루는 것은 이자가 붙는 부채입니다.
진단:
git log --oneline main..feature/redesign | wc -l # 브랜치 고유 커밋 수
git log --oneline feature/redesign..main | wc -l # 놓친 main 변경 수(클수록 위험)
해결: 큰 작업도 작게 쪼개 자주 통합합니다 — 미완성은 기능 플래그로 숨겨 main에 계속 머지(Trunk-based 원리)하거나, 최소한 main을 주기적으로 브랜치에 합쳐(rebase/merge) 차이를 작게 유지합니다. 이미 벌어졌다면 단계적으로(파일 그룹별) 나눠 머지합니다. 브랜치 전략의 제1원칙은 "통합을 미루지 마라"입니다.
심화 — 전략은 고르는 게 아니라 감당하는 것
심화: 다른 팀의 전략을 베끼면 생기는 일 — 전제 조건과 안티패턴
세 전략의 구조를 아는 것과 우리 팀에서 굴러가게 하는 것은 다른 문제입니다. 브랜치 전략 사고의 대부분은 전략 자체가 아니라 전제 조건에서 납니다.
- Trunk-based는 도구가 아니라 역량의 결과입니다: 자동 테스트 커버리지, 10분 안에 끝나는 CI, 당일 리뷰가 갖춰지지 않은 팀이 브랜치만 짧게 만들면 'main이 자주 깨지는 전략'이 됩니다. 전제가 없으면 GitHub Flow에서 시작해 CI/CD 파이프라인과 테스트를 먼저 쌓는 것이 순서입니다.
- 형해화된 Git Flow: 웹 서비스 팀이 관성으로 Git Flow를 쓰면 release 브랜치는 안 쓰고 develop은 main의 복사본이 됩니다 — 머지만 두 번 하는 관료 절차. develop과 main의 diff가 늘 0에 가깝다면 GitHub Flow로 줄이라는 신호입니다.
- 환경 브랜치 안티패턴: dev·stg·prod 브랜치를 따로 두고 cherry-pick으로 '승격'하는 방식은 환경마다 히스토리가 달라져(드리프트), stg에서 검증한 코드와 prod에 올라간 코드가 사실상 다른 코드가 됩니다. 승격은 브랜치 간 복사가 아니라 같은 커밋·같은 산출물에 태그를 달아 옮기는 것이어야 합니다.
- 기능 플래그는 만들 때가 아니라 지울 때를 계획합니다: Trunk-based를 받치는 플래그는 출시 후 제거하지 않으면 죽은 분기가 코드에 계속 쌓입니다. 플래그마다 소유자와 제거 기한을 붙이는 팀만 이 전략을 오래 유지합니다.
전략 이름을 정하는 회의보다, "우리 팀이 어느 전제를 갖췄고 무엇이 빠졌나"를 점검하는 회의가 사고를 줄입니다.
상황: 2주 전 장애 때 prod 태그 v1.2.0에서 hotfix 브랜치를 따 패치하고 v1.2.1로 긴급 배포해 상황을 종료했습니다. 오늘 정기 릴리스 v1.3.0을 배포하자 같은 결제 버그가 같은 스택트레이스로 재발합니다 — 고객 문의가 다시 쏟아집니다.
원인: 핫픽스가 prod 태그에서 분기해 배포까지만 되고 main에 백포트되지 않았습니다. v1.3.0은 main에서 만들어졌으므로 수정이 빠진 코드로 릴리스된 것 — 정기 릴리스가 핫픽스를 '덮어쓴' 셈입니다. 긴급 상황이 끝나는 순간 백포트를 잊는 것이 이 사고의 전형적인 경로입니다.
진단:
git branch --contains 7d3f2a1 # 핫픽스 커밋이 hotfix/1.2.1에만 있고 main에 없음
git tag --contains 7d3f2a1 # v1.2.1에만 포함, v1.3.0에 없음 → 백포트 누락 확정
git log v1.3.0 --oneline --grep='중복 결제' # 릴리스에 수정 커밋 부재 재확인
해결: 즉시 핫픽스 커밋을 main에 머지(또는 cherry-pick)하고 v1.3.1로 재배포합니다. 재발 방지: 핫픽스 절차의 마지막 단계에 'main 백포트'를 명시해 배포 완료 ≠ 상황 종료로 만들고, 가능하면 hotfix 브랜치 머지 시 main 대상 PR을 자동 생성합니다. 릴리스 체크리스트에 "이전 핫픽스 커밋이 모두 포함됐는가(git tag --contains)"를 넣으면 같은 사고를 릴리스 전에 잡을 수 있습니다.
확대
위 그림처럼 PR은 CI 자동 검증과 코드 리뷰 승인이라는 두 게이트를 통과해야만 main 브랜치에 병합됩니다.
인프라/SRE로서 브랜치 전략은 곧 당신이 설계할 배포 파이프라인의 명세입니다 — "main 머지 → staging 자동 배포, 태그 → prod, hotfix/* → prod 직행" 같은 규칙을 CI/CD에 박습니다(CI/CD 파이프라인). 전략이 모호하면 "어느 코드가 prod에 떠 있나"를 아무도 확신 못 해 배포 사고가 납니다. 또한 핫픽스 경로를 미리 설계해 두면, 긴급 보안 패치를 미완성 기능과 섞지 않고 prod 태그에서 분기해 안전하게 배포할 수 있습니다. PM은 브랜치 전략으로 "배포됨 vs 노출됨(기능 플래그)"을 구분해 릴리스 일정을 더 유연하게 가져갑니다.
다음 모듈에서는 브랜치를 main에 합치기 전 거치는 품질 관문 — PR과 코드 리뷰 문화를 다룹니다.
실전 랩으로 손에 익히기: 브랜치 전략 선택 실습 — 팀 상황을 진단해 전략을 고르고 브랜치 규칙·보호 장치까지 설계합니다.