퇴사몬 프로젝트 회고 - 브랜치 전략
4분 읽기
작년 3월 퇴사몬 프로젝트를 시작하며, 개발자 3명(백엔드 1명, 프론트엔드 2명)이 첫 화상회의를 하며 이런저런 고민을 나눴습니다. GitHub Organization 생성부터 API 문서화 도구, 배포 방식, 그리고 브랜치 전략까지 개발 환경 전반을 먼저 고민해보는 자리였습니다. 프론트엔드 레포는 2명이서만 작업하는 환경이었으니, 규모만 보면 브랜치 전략은 크게 고민할 문제가 아니었습니다. 그래도 이 기회에 기준을 잘 세워봐야겠다는 마음으로 여러 블로그 글과 문서를 참고했던 기억이 납니다.
그때 찾아본 정보들과 나눈 대화들을 언젠가 정리해 둬야지 하면서도 시간이 없어 계속 미뤄왔는데, 더 흐려지기 전에 오늘에서야 기록으로 남깁니다.
후보에 올랐던 전략들링크를 제목에 복사
당시 찾아본 자료들은 대체로 1) 팀 규모 2) 배포 주기 3) 버전 관리의 필요성을 축으로 전략을 나누고 있었습니다. 대규모 정기 배포라면 Git Flow, 소규모 상시 배포라면 GitHub Flow, 오픈 소스라면 Forking Workflow 이런 식이었습니다.
GitLab Flow, TBD까지 다양하게 테이블에 올려 두긴 했지만, 가장 문서화가 잘 되어 있고 우리에게 익숙했던 Git Flow와 GitHub Flow 두 가지가 남았습니다.
사실 첫 회의에서 딱 부러지게 결론이 나지는 않았습니다. "회사에서는 어떻게 하세요?", "Jira 이슈로 티켓 따고 브랜치 만들어서 작업해요" 같은 각자의 경험담을 나누는 선에서 마무리됐습니다. 이대로면 각자 익숙한 방식대로 흘러가겠다 싶어서, 남은 두 후보를 기준을 세워 비교해 보기로 했습니다.
Git Flow링크를 제목에 복사
핵심은 "배포된 것"과 "개발 중인 것"의 분리입니다. master는 배포 이력만 관리하고 일상 개발은 develop에서 이루어지며, 출시 준비는 release, 긴급 수정은 hotfix라는 전용 브랜치로 격리합니다.
당시에는 QA나 릴리스 준비 기간을 물리적으로 분리해둘 수 있다는 점이 든든해 보였습니다. 반면 둘이서 브랜치 다섯 종류와 그 사이의 병합 경로를 계속 관리해야 한다는 건, 규칙을 지키는 것 자체가 일이 되겠다 싶어 부담스러웠습니다.
GitHub Flow링크를 제목에 복사
GitHub Flow는 복잡한 규칙 대신 "main은 항상 배포 가능한 상태여야 한다"는 원칙 하나만 지키면 됩니다. 모든 작업은 topic 브랜치에서 PR로 병합되고, 버그 수정도 예외가 아닙니다.
지켜야 할 규칙이 사실상 하나뿐이고 CI/CD와도 잘 맞아서, 둘이서 빠르게 개발하기에는 이쪽이 훨씬 가벼워 보였습니다. 다만 브랜치가 main 하나뿐이라 배포 전에 QA 중인 코드를 따로 모아둘 곳이 없다는 점은 조금 걱정됐습니다.
두 전략을 비교하면 아래와 같습니다.
| Git Flow | GitHub Flow | |
|---|---|---|
| 항상 유지되는 브랜치 | master + develop | main 하나 |
| 보조 브랜치 | feature / release / hotfix | topic 하나 |
| 배포 단위 | 버전 (정기 릴리스) | 커밋 (상시 배포) |
| 긴급 수정 | hotfix로 격리 | topic에서 동일하게 처리 |
| 어울리는 환경 | 정기 배포 · 버저닝 | CI/CD · 상시 배포 |
우리 상황을 앞서 본 세 가지 축에 대입해 보니 답은 명확해 보였습니다. 저장소를 공유하는 프론트엔드 인원은 2명이라 충돌이나 컨텍스트 꼬임이 발생할 가능성이 낮았고, 별도의 정형화된 배포 주기도 없었으며, 버전을 매겨 릴리스 이력을 관리해야 하는 애플리케이션도 아니었습니다.
여기에 더해, Prography 활동 기간 동안 주요 개발이 집중적으로 이루어지고 서비스 유지 기간이나 향후 버전 관리 계획이 명확하지 않았던 점까지 고려하면, 비교적 간결하고 상시 배포에 적합한 GitHub Flow가 가장 현실적이라고 판단했습니다.
실제로는 어떻게 굴러갔을까요?링크를 제목에 복사
기획이 구체화되면서 상황이 달라졌습니다. 1차로 MVP를 빠르게 출시하고 2차로 정식 배포를 계획하게 되었고, 이 사이에 QA/QC 단계가 포함된 것입니다.
앞서 본 "출시를 준비하는 상태"를 담아둘 자리가 없다는 점이 문제가 됐고, 결국 develop에서 개발을 이어가면서 release로 출시 준비 흐름을 격리할 수 있는 Git Flow를 따르게 되었습니다.
그 결정이 실제로 어떻게 굴러갔는지, 이 글을 쓰면서 궁금해져 레포의 PR 이력을 다시 열어봤습니다. 결과가 꽤 재미있었습니다.
- 초기 세팅(husky, 커밋 컨벤션, 이슈·PR 템플릿 등) 약 한 달은
main에서 직접 커밋하며 진행했고, 첫 기능 PR부터feature→develop흐름이 시작됐습니다. feature→develop흐름은 끝까지 잘 지켜졌습니다. 약 5개월의 개발 기간 동안 82개의 PR이 전부 토픽 브랜치에서develop으로 병합됐습니다.release브랜치는 한 번도 만들지 않았습니다. 태그도 0개입니다.hotfix도 없었습니다. QA에서 나온 수정사항은bugfix/QA,bugfix/design-qc같은 토픽 브랜치로develop에 직접 반영됐습니다.main은develop분기 이후 방치됐습니다.develop→main병합은 개발이 마무리되고 두 달 뒤에 딱 한 번, "Update to Main branch"라는 PR로 이루어졌습니다.- 정작 실제 배포는 dockerfile이 있는 별도의
deploy브랜치가 담당하고 있었습니다.
결과적으로 Git Flow를 채택하고도, 우리가 실제로 운영한 것은 develop이 main 역할을 하는 GitHub Flow에 가까운 무언가였습니다. Git Flow를 선택하게 만든 바로 그 QA 단계조차, release 브랜치가 아니라 평범한 토픽 브랜치로 소화됐습니다. 공교롭게도 이 모습은, 검토 초반에 내려놓았던 GitLab Flow의 환경 브랜치 방식과 가장 닮아 있었습니다.
왜 이렇게 됐을까요?링크를 제목에 복사
Git Flow를 따르게 된 이유였던 "QA 분리"가 틀렸던 건 아닙니다. 다만 2인 팀의 QA는 release라는 전용 브랜치가 필요할 만큼 크지 않았습니다. 개발을 멈추고 QA 수정만 몰아서 하는 기간에는 어차피 develop에 다른 작업이 들어오지 않으니, 분리할 대상 자체가 없었던 것입니다. 브랜치 전략의 규칙은 지키는 데 계속 비용이 드는데, 인원이 적을수록 그 부담이 상대적으로 커진다는 걸 직접 확인한 셈입니다.
main이 방치된 것도 같은 이유입니다. 실제 배포는 EC2 위의 deploy 브랜치에서 이루어졌기 때문에, Git Flow에서 master가 맡아야 할 "배포 이력 관리"라는 역할이 사라져 버렸습니다. 브랜치 전략은 그것만 따로 정하는 게 아니라 배포 방식과 함께 설계해야 한다는 것, 이게 이 프로젝트가 남긴 가장 큰 교훈이었습니다.
돌아보면링크를 제목에 복사
다시 그때로 돌아간다면, GitHub Flow에 배포 브랜치 하나만 더하는 정도로 충분했을 것 같습니다. 실제 운영도 그런 모습에 가까웠기 때문입니다.
공교롭게도 그때도 Vercel을 쓰고 있었습니다. PR을 올릴 때마다 프리뷰 배포가 뜨고 있었는데, 그걸로 "출시 전 상태"를 미리 확인할 수 있다는 걸 그때는 몰랐습니다. GitHub Flow만으로 충분한 환경이 이미 갖춰져 있었던 겁니다.
그렇다고 그때의 논의가 쓸모없었다고 생각하지는 않습니다. 시작하기 전에 한번 이렇게 짚어 뒀기 때문에, 상황이 바뀔 때 왜 이 전략을 골랐는지 설명할 수 있었고, 1년 뒤에 이렇게 결정과 실제가 어떻게 달랐는지 되짚어볼 수도 있었습니다.
관련 글
블로그를 만들고 싶었던 게 아니라, 잘 만든 블로그를 갖고 싶었던 거였다
중꺾그마 = 중요한 건 꺾였는데도 그냥 하는 마음
무엇이 탁월한 개발자를 만드는가: 자가 점검해 보기
탁월한 엔지니어의 다섯 가지 핵심 역량을 정리하고, 주니어·프론트엔드 개발자의 관점에서 스스로를 점검한 기록입니다.
모든 글