Git을 사용하는 개발자라면 한 번쯤은 Branch 전략에 대해 고민해 본 적이 있으실 텐데요! 저도 회사에서 기존에 사용하던 TBD 전략에서 Git-Flow로 전환하며 많은 고민을 했었습니다.
이번 포스팅에서는 TBD 전략이 왜 적합하지 않았는지, 그리고 Git-Flow로 변경하며 어떤 개선을 이뤘는지에 대해 공유해보려 합니다. 🥸
TBD(Trunk-Based Development) 전략은 모든 개발자가 하나의 main 브랜치(트렁크)를 중심으로 작업을 진행하는 Git 브랜치 전략입니다. 이 전략에서 중요한 점은 작은 단위로 자주 커밋하고, 개발자가 빠르게 main 브랜치에 병합하는 것입니다.
개발자는 feature 브랜치에서 작업할 수 있지만, 이 브랜치를 오래 유지하지 않고 작은 작업 단위로 main 브랜치에 빠르게 병합합니다. 작업이 완료되면 PR을 생성하여 코드 리뷰를 받으며, 리뷰가 완료된 후 main 브랜치에 병합됩니다. 이러한 프로세스는 가능한 자주 일어나며, 모든 개발자는 최신 main 브랜치를 기반으로 작업을 계속합니다.
당시 서비스가 빠르게 성장하고 있었기 때문입니다. 이로 인해 잦은 배포가 이루어졌고, 배포 주기가 정해져 있지 않은 상황에서 기획과 디자인이 완료되면 곧바로 개발에 착수하여, 개발이 끝나는 즉시 운영 서버에 배포하는 방식으로 진행되었습니다.
이러한 방식은 빠르게 기능을 개발하고, 유저의 반응을 확인한 뒤, 이를 기반으로 기능을 수정 및 보완하는 것을 목표로 했습니다. 따라서 배포 과정에서 복잡한 절차를 줄이고자 했습니다.
또한, 당시 개발 인원이 많지 않았기 때문에 긴 배포 프로세스가 오히려 비효율적이라고 판단되었습니다. TBD 전략은 작은 단위로 작업을 자주 병합하고, 빠르게 배포할 수 있는 방식을 제공했기 때문에 이러한 요구를 충족시키기에 적합하다고 보아 선택하게 되었습니다.
하지만 서비스 안정화와 규모 확장으로 인해 다음과 같은 문제가 발생했습니다.
서비스의 규모가 커지고, 장기간 프로젝트, 단기간 작업, 유지보수 작업이 동시에 진행되면서 개발자들 간 배포 시점이 서로 달라지는 상황이 빈번해졌습니다. TBD에서는 모든 작업이 main 브랜치에 자주 병합되기 때문에, 이러한 배포 시기의 불일치는 예기치 않은 충돌이나 의존성 문제를 발생시켰고, 결과적으로 배포 프로세스의 효율성을 저하시켰습니다.
작업 간 배포 시점의 차이로 인해 이미 배포된 코드와 배포 대기 중인 코드가 동시에 main 브랜치에 존재하는 상황이 생겼습니다. 이로 인해 미사용 코드 정리, 충돌 해결, 배포 이후의 추가적인 수정 작업 등 유지보수에 많은 시간이 소요되었습니다. 이러한 문제는 코드의 복잡성을 증가시키고, 작업 효율성을 저하시키는 결과를 낳았습니다.
Git-Flow 전략은 소프트웨어 개발에서 효율적인 브랜치 관리와 배포 프로세스를 지원하는 Git 브랜칭 모델입니다. 주요 브랜치로는 main(배포용), develop(개발용), feature(기능 개발), release(배포 준비), hotfix(긴급 수정) 브랜치가 있으며, 각각 명확한 목적과 작업 흐름을 가지고 있습니다.
Git-Flow 전략을 선택한 이유는 작업 유형과 배포 주기를 명확히 분리하여 안정성을 확보하기 위함이었습니다. TBD 전략에서는 작업 간 배포 시점의 불일치로 인해 충돌과 의존성 문제가 발생하고, 배포되지 않은 코드와 배포된 코드가 동시에 main 브랜치에 존재하는 상황이 빈번했기 때문에, 이를 해결할 필요가 있었습니다. Git-Flow는 main, develop, feature, release, hotfix 브랜치를 통해 각 작업의 목적과 배포 프로세스를 명확히 구분하고, 체계적인 관리로 배포 안정성을 높일 수 있어 기존의 문제를 해결하는 데 적합했습니다.
저희 팀은 Git-Flow 전략을 원칙대로 사용하지 않고, 프로젝트 특성과 배포 프로세스에 맞게 변형하여 적용했습니다. 이를 통해 개발 완료와 배포 시기를 유연하게 분리하고, 작업 효율성과 코드 관리를 높였습니다. 아래는 세부적인 브랜치 구조와 사용 방식입니다.
운영 서버에 배포된 안정된 코드를 관리하는 브랜치입니다. 버그 수정이나 긴급 작업 완료 후 이곳에 병합됩니다.
배포 직전 상태의 feature 브랜치들을 모아 관리하는 브랜치입니다. 배포 준비가 완료된 코드는 이 브랜치로 병합되며, 최종적으로 Main 브랜치로 PR을 생성해 배포를 진행합니다.
release에 병합된 feature 브랜치는 삭제하여 브랜치 관리를 간소화합니다.
QA 및 테스트를 위한 브랜치로, 배포 시기와 상관없이 개발이 완료된 feature 브랜치들을 모아 관리합니다.
Release 브랜치와의 차이점
- Stage 브랜치는 개발 완료 시점에 병합되며, 배포 날짜에 구애받지 않습니다.
- 이는 작업 완료와 배포를 분리하여, 긴 QA 과정이 필요한 작업과 즉시 배포 가능한 작업을 구분하기 위함이었습니다.
각 기능 개발을 위한 브랜치로, 작업이 완료되면 stage 브랜치로 병합하고 QA를 진행합니다. QA가 완료되고 배포 시점이 다가오면, release 브랜치로 병합합니다.
운영 중 발생한 버그나 긴급 CS 이슈를 해결하기 위한 브랜치입니다. 작업 완료 후 main 브랜치로 PR을 생성해 바로 병합하고, 이후 main 브랜치와 release 브랜치를 동기화하여 배포 상태를 유지합니다.
코드 리팩토링 작업을 위한 브랜치입니다.
feature 브랜치를 release 브랜치로 병합할 때는 Squash Merge를 사용했습니다.
커밋 기록의 간결화
Squash Merge는 작업 과정을 한 번에 합쳐 하나의 커밋으로 병합하기 때문에, 불필요한 커밋 로그를 줄이고 히스토리를 깔끔하게 유지할 수 있습니다.
PR 리뷰 과정 간소화
커밋 수가 많을 경우 PR 리뷰가 복잡해질 수 있지만, Squash Merge를 통해 PR을 단일 작업 단위로 처리할 수 있습니다.
코드베이스 관리 효율성
병합 이후 각 브랜치의 기록을 단순화하여, Git 히스토리를 추적하거나 문제가 발생했을 때 디버깅을 쉽게 할 수 있습니다.
TBD 전략은 초기에는 빠르고 간소화된 배포 프로세스를 지원해 효과적이었지만, 서비스가 성장하고 팀 규모와 작업 범위가 확대되면서 여러 문제들이 발견됐습니다. 이러 문제를 해결하기 위해 Git-Flow 전략을 프로젝트에 맞게 변형하여 도입함으로써 작업과 배포를 명확히 분리하고 효율성을 높일 수 있었던 것 같습니다!
비록 전보다 지켜야하는 규칙과 관리해야하는 브랜치들이 많아지기는 했지만, 빠르고 간편한게 무조건 좋은 것 만은 아니라는 것도 깨달았습니다!ㅎㅎ 이번 경험을 통해 프로젝트 환경과 팀의 요구에 따라 브랜치 전략을 유연하게 조정하는 것이 중요하다는 것을 배울 수 있었습니다. 이런 시행착오를 통해 더 발전할 수 있을거라고 믿으며 우리 모두 상황에 맞는 브랜치 전략을 선택합시다~ ! 🙌🏻