Git Flow와 브랜치 전략의 선택 기준
Git Flow, GitHub Flow, Trunk-Based Development가 어떤 문제를 해결하는지와 각각의 운영 조건을 비교한다. 브랜치 보호 규칙, 머지 전략, Feature Flag, 실무 실패 패턴까지 연결해 팀 상황에 맞는 선택 기준을 정리한다.
Script Companion
오디오와 함께 스크립트 보기
- 01
브랜치 전략은 Git을 예쁘게 쓰기 위한 규칙이 아니라, 여러 사람이 같은 제품을 동시에 바꿀 때 생기는 위험을 흡수하는 운영 방식이다. 개발자 여러 명이 main 브랜치에 바로 커밋하면 결제 기능, 인증 수정, 긴급 버그 픽스가 한 흐름에 섞이고, 충돌과 테스트되지 않은 배포, 롤백의 어려움이 한꺼번에 나타난다. 그래서 브랜치 전략의 핵심은 병렬 개발을 분리하고, 리뷰와 테스트를 통과한 코드만 합류시키며, 문제가 생겼을 때 어느 지점으로 되돌릴지 이력을 남기는 데 있다.
- 02
현업에서 브랜치 전략은 팀의 속도와 안정성에 직접 연결된다. DORA의 2021 State of DevOps Report는 신뢰성 목표를 달성한 elite performer가 낮은 성과 그룹보다 Trunk-Based Development를 사용할 가능성이 2.3배 높다고 보고했다. DORA의 TBD capability 문서는 이를 운영 지표로 더 구체화한다. 활성 브랜치 3개 이하, trunk 병합 하루 1회 이상, 코드 프리즈와 별도 통합 단계 제거가 권장 상태다. 결국 질문은 어떤 전략이 더 멋진가가 아니라, 우리 팀이 충돌, 리뷰, 배포를 얼마나 자주 감당할 수 있는가다.
- 03
Git Flow는 대형 마트의 물류 시스템처럼 이해할 수 있다. 배포된 프로덕션 코드는 main에 있고, 통합 개발은 develop에서 진행되며, 기능은 feature 브랜치에서 만들고, 배포 준비는 release 브랜치에서 다듬고, 긴급 패치는 hotfix 브랜치로 처리한다. 상품이 입고 창고와 검품실을 거쳐 진열대에 오르듯, Git Flow는 기능 개발과 QA, 배포 단계를 분리한다. hotfix만은 프로덕션 긴급 패치이기 때문에 main에서 시작해 main과 develop 양쪽으로 다시 반영되어야 한다.
- 04
Git Flow에서 중요한 세부 규칙은 no fast-forward 머지다. fast-forward로 머지하면 feature 브랜치의 커밋이 main 이력에 그대로 이어붙고, 나중에 기능 하나를 통째로 되돌리려면 관련 커밋을 하나씩 찾아서 되돌려야 한다. 반면 no fast-forward는 머지 커밋을 남겨서 기능 묶음을 하나의 감사 단위로 보존한다. Git 공식 문서 기준으로도 fast-forward는 가능할 때 브랜치 포인터만 이동하고 머지 커밋을 만들지 않지만, no fast-forward는 가능한 상황에서도 머지 커밋을 만든다. Git Flow에서는 이 기록이 release에 어떤 기능 묶음이 들어갔는지 추적하는 장치가 된다.
- 05
Git Flow의 장점은 릴리즈 버전 관리가 명확하고, 여러 버전을 동시에 지원해야 하는 모바일 앱이나 패키지 라이브러리 같은 상황에 맞으며, QA 팀이 따로 있는 조직에서 흐름이 분명하다는 점이다. 반대로 브랜치가 많고 develop에서 release를 거쳐 main으로 가는 단계가 길어 배포까지 시간이 걸린다. CI/CD를 구축해도 흐름 자체가 긴 경우에는 배포 속도 향상이 제한된다. 원저자 Vincent Driessen 본인도 2020년에 웹 앱에는 Git Flow가 맞지 않는다고 인정했다는 점은, 이 전략이 모든 서비스의 기본값은 아니라는 신호다.
- 06
GitHub Flow는 Git Flow보다 단순한 전략이다. main은 항상 배포 가능한 상태를 유지하고, 모든 작업은 feature, fix, chore 같은 작업 브랜치에서 진행한 뒤 Pull Request로 검수되어 main에 합쳐진다. 편의점 상품 입고처럼 발주하고, 입고 검수하고, 바로 진열하는 흐름에 가깝다. 핵심 규율은 main이 항상 배포 가능해야 한다는 점이다. 이 규율이 무너지면 GitHub Flow는 단순한 협업 모델이 아니라, 검증 없이 main에 쌓이는 무규칙 feature branch가 되기 쉽다.
- 07
GitHub Flow를 지탱하는 장치는 Branch Protection Rules다. 직접 push를 막고 Pull Request만 허용하며, 최소 승인 수를 요구하고, CI 상태 검사를 통과해야 머지를 허용하게 만든다. GitHub 공식 문서 기준으로 required status check는 successful, skipped, neutral 상태여야 병합될 수 있고, strict 모드에서는 base branch 최신화까지 요구한다. strict 모드를 끄면 CI가 통과한 뒤 다른 Pull Request가 먼저 머지되어도 현재 Pull Request를 다시 검증하지 않을 수 있다. 화면에는 green check가 남아 안전해 보이지만, 병합 후 main에서 조합 충돌이 터지는 silent failure가 될 수 있다.
- 08
Trunk-Based Development, 즉 TBD는 모든 개발자가 하루에 1회에서 2회 이상 main, 또는 trunk에 직접 병합하는 방식이다. 브랜치를 만들더라도 최대 1일에서 2일 안에 병합하고, 미완성 기능은 Feature Flag로 감춘다. 여기서 중요한 원리는 불일치가 누적되기 전에 흡수한다는 것이다. 머지 충돌은 두 브랜치가 같은 코드 영역을 서로 다르게 수정할 때 발생하므로, 브랜치가 2일 살아 있으면 2일치 차이만 쌓이지만, 2주 살아 있으면 14일치 차이가 쌓인다. 브랜치 수명이 짧을수록 충돌 가능성이 줄어드는 이유가 여기에 있다.
- 09
TBD에서 Feature Flag는 선택 장식이 아니라 필수 장치다. TBD에서는 기능이 완성되기 전에도 코드가 main에 병합될 수 있으므로, 코드는 배포됐지만 기능은 꺼져 있는 상태를 만들어야 한다. 이 구조는 통합 단위와 사용자 노출 단위를 분리한다는 원리로 설명할 수 있다. K8s 카나리 배포에서 Argo Rollouts가 새 버전 Pod를 넣고 setWeight: 10으로 트래픽 10%만 노출하는 방식, DB 스키마 expand와 contract 마이그레이션에서 새 컬럼과 옛 컬럼을 잠시 공존시키는 방식, A/B 실험과 Dark Launch에서 같은 코드의 노출 비율을 다르게 가져가는 방식 모두 유사한 원리가 보인다.
- 10
TBD의 장점은 배포 빈도를 크게 높이고, 짧은 브랜치 수명으로 머지 충돌을 줄이며, CI/CD 파이프라인과 강하게 맞물린다는 점이다. 하지만 조건도 강하다. 자동화 테스트 커버리지가 약하거나, 모든 커밋에서 CI가 실행되지 않거나, Feature Flag 없이 미완성 기능을 main에 합치면 main의 신뢰도가 무너진다. 문서의 기준으로는 CI 실행 시간이 10분 미만, 이상적으로는 5분 미만이어야 하고, 핵심 로직 커버리지는 70% 이상이어야 한다. PR 수명도 평균 2일 미만이어야 충돌 해결 비용이 TBD의 장점을 상쇄하지 않는다.
- 11
머지 방식 선택도 브랜치 전략의 일부다. Merge Commit은 원본 이력을 보존하므로 오래 유지할 브랜치나 감사 추적이 필요한 상황에 맞지만, git log가 복잡해질 수 있다. Squash Merge는 feature 브랜치의 여러 커밋을 하나로 압축해 이력을 깔끔하게 만들기 때문에 작업 브랜치를 완료 후 삭제할 때 잘 맞지만, git bisect가 어려워질 수 있다. Rebase는 선형 이력을 만들지만 커밋 해시를 바꾸므로 공유 브랜치에는 절대 사용하면 안 된다. 팀 컨벤션을 통일하려면 GitHub 설정에서 여러 방식을 열어두기보다 선택한 방식 하나만 남기는 편이 낫다.
- 12
실무 선택 기준은 팀 규모와 배포 방식으로 좁혀볼 수 있다. 개발자 2명에서 5명 규모이고 빠른 배포가 필요하면 GitHub Flow가 현실적이다. main 머지 즉시 AWS ECS나 Lambda 자동 배포로 이어지고, 복잡한 브랜치 관리 오버헤드가 없기 때문이다. 5명에서 15명 규모이고 버전 릴리즈가 존재하면 Git Flow가 QA와 hotfix 흐름을 분리하는 데 도움이 된다. 고성능 팀이고 강한 CI/CD 문화가 있으며 Feature Flag 인프라가 있다면 TBD를 검토할 수 있다. Google과 Facebook 사례도 강한 테스트와 flag 인프라가 전제였다는 점을 같이 봐야 한다.
- 13
BackOps 같은 Nest.js와 AWS 기반 운영 도구라면 기본값은 GitHub Flow가 가장 현실적이다. 개발자 4명, ECS 배포 주 3회에서 5회, 모바일 앱처럼 구버전 동시 지원이 없는 서비스라면 main 보호 규칙, Pull Request 기반 리뷰, Squash Merge, staging 자동 배포로 시작하는 흐름이 맞다. 이후 PR 평균 수명이 1일 안쪽이고, 테스트가 핵심 API 경로를 충분히 막아주며, AWS AppConfig 같은 Flag 시스템으로 신규 기능을 OFF 배포할 수 있을 때만 TBD로 좁히는 식이다. 반대로 고객사별 설치형 버전이나 장기 지원 브랜치가 생기면 release와 hotfix 분리를 가진 Git Flow의 이득이 다시 커진다.
- 14
대표적인 실패 패턴은 전략의 규칙을 일부만 가져올 때 생긴다. Squash Merge 후 같은 feature 브랜치를 계속 쓰면 원본 커밋과 main의 squash 커밋을 Git이 다른 변경사항으로 인식해 이미 반영된 내용이 다시 충돌로 나타날 수 있다. Git Flow에서 hotfix를 main에만 넣고 develop에 반영하지 않으면 다음 release에서 같은 버그가 재발한다. TBD에서는 오래된 Feature Flag를 정리하지 않으면 코드 경로가 늘어나 기술 부채가 되고, CI와 테스트와 Feature Flag 없이 전환하면 노출되지 않은 미완성 코드가 main에 누적된다. 정리하면 Git Flow는 버전 관리 명확성, GitHub Flow는 단순성과 속도, TBD는 최고의 배포 빈도를 추구하며, 선택 기준은 팀 규모, 배포 주기, 테스트 문화다.
같은 레이어
L5에서 이어 듣기
- 오디오 파일
- /podcasts/l5-git-flow.mp3