
최근 멋사FE 스쿨에서 오픈소프 프로젝트가 만들어졌다. 협업을 통한 프로젝트를 경험해 볼 수 있을 것 같아 참여하게 되었고 나는 기획, 디자인, 프론트엔드 부분에 기여하고 있다.
이 프로젝트는 알고뷰라는 코딩테스트에서 어떤 매소드를 얼마나 쓰는지 체크해 볼 수 있는 프로젝트다.
생각보다 많은 인원이 참여하였고 많은 인원이 참여하는 만큼 효율적인 진행을 위해 투표로 컨벤션을 정하게 되었다.
그 과정에서 브랜치 전략에 대해 알게 되었고 더 깔끔하게 기억하기 위해 정리하려 한다.
우리는 왜 브랜치를 사용할까?
동시 작업: 여러 개발자들이 동시에 개발 작업을 수행할 때, 각자의 브랜치에서 작업을 진행하면 독립적인 공간에서 작업할 수 있다. 즉 작업 내용을 서로 간섭받지 않고 병렬적인 관계에서 진행할 수 있다.
기능 개발: 새로운 기능을 개발할 때, 기존의 안정된 코드에 영향을 주지 않도록 하기 위해 브랜치를 생성한다. 이렇게 하면 새로운 기능을 개발하고 테스트할 수 있으며, 문제가 발생하면 기존의 안정된 코드로 돌아갈 수 도 있다.
버그 수정: 버그 수정을 위해 브랜치를 생성하면, 기존의 안정된 코드는 유지한 채 버그를 수정하고 테스트할 수 있다. 버그 수정이 완료되면, 수정된 코드를 메인 브랜치에 병합(merge)하여 적용할 수 있다.
실험 및 테스트: 새로운 아이디어나 실험적인 변경 사항을 테스트하기 위해 브랜치를 사용할 수 있다. 실험적인 것들을 맘편하게 시도해보고 실험 결과가 만족스러울 때 해당 브랜치를 메인 브랜치에 병합하여 적용할 수 있다.
브랜치를 따로 생성하여 작업하지 않고 메인 브랜치에서만 작업한다며 어떨까?
오직 메인 브랜치에서 수 많은 개발자들이 협업한다면,

VCS (Version Control Systems)Git Flow는 Vincent Driessen이 그의 블로그에 2010년에 올린 A successful Git branching model 이라는 글이 인기를 끌며 대중적으로 사용되게 된 브랜치 전략이다.
그러나 10년 뒤 이 글에 대한 반성의 글을 적는데 그 내용을 요약하면
Git-Flow는 등장하고 10년 넘게 표준처럼 자리잡고, 더 나아가 마치 만병통치약처럼 사용되었다. 현재는Git으로 관리되는 인기있는 유형의 소프트웨어가 웹 어플리케이션으로 이동하고 있다. 웹 어플리케이션은 일반적으로 롤백되지 않고, 지속적으로 제공되므로 여러 버전의 소프트웨어를 지원할 필요가 없다.
웹 어플리케이션은 내가 10년전 블로그 글을 쓸때에는 염두해둔 소프트웨어 유형이 아니다. 팀이 소프트웨어를 지속적으로 제공한다면,Git Flow대신Github Flow와 같은 더 단순한 워크플로우를 채택할 것을 제안한다.
그러나 명시적으로 버전을 관리해야하는 소프트웨어를 개발한다면, 여전히Git Flow가 적합할 수 있다.
즉 Git Flow는 명시적으로 버전관리가 필요한 이를 테면, 스마트폰 어플리케이션, 오픈소스 라이브러리/프레임워크 등의 프로젝트에 적합하다.
우아한 형제들 기술 블로그에 기재된 인기글 중 하나인 우린 Git-flow를 사용하고 있어요 글을 작성한 팀도 안드로이드 앱 개발팀이다.
Git Flow는 크게 Main 브랜치, Develop 브랜치, Supporting 브랜치로 구분하여 브랜치를 관리한다. 이때, Supporting 브랜치는 또 다시 Feature 브랜치, Release 브랜치, Hotfix 브랜치로 나뉜다.

Main 브랜치는 출시 가능한 프로덕션 코드를 모아두는 브랜치이다.
Main 브랜치는 프로젝트 시작 시 생성되며, 개발 프로세스 전반에 걸쳐 유지된다. 배포된 각 버전을 Tag를 이용해 표시해둔다.
다음 버전 개발을 위한 코드를 모아두는 브랜치다.
개발이 완료되면, Main 브랜치로 merge된다.
하나의 기능을 개발하기 위한 브랜치다.
Develop 브랜치에서 생성하며, 기능이 개발 완료되면 다시 Develop 브랜치로 merge된다. merge할때 주의점은 Fast-Forward로 merge하지 않고, Merge Commit을 생성하며 merge를 해주어야 한다. 이렇게해야 히스토리가 특정 기능 단위로 묶이게 된다.
네이밍은 feature/branch-name 과 같은 형태로 생성한다.
소프트웨어 배포를 준비하기 위한 브랜치이다.
Develop 브랜치에서 생성하며, 버전 이름 등의 소소한 데이터를 수정하거나 배포전 사소한 버그를 수정하기 위해 사용된다. 배포 준비가 완료되었다면 Main과 Develop 브랜치에 둘다 merge한다. 이때, Main 브랜치에는 태그를 이용하여 버전을 표시한다.
Release 브랜치를 따로 운용함으로써, 배포 업무와 관련없는 팀원들은 병렬적으로 Feature 브랜치에서 이어서 기능을 개발할 수 있게된다.
네이밍은 release/v1.1 과 같은 형태로 생성한다.
이미 배포된 버전에 문제가 발생했다면, Hotfix 브랜치를 사용하여 문제를 해결한다.
Main 브랜치에서 생성하며, 문제 해결이 완료되면 Main과 Develop 브랜치에 둘다 merge한다. Release 브랜치와 마찬가지로 Hotfix 브랜치를 따로 운용함으로써, 핫픽스 업무와 관련없는 팀은 병렬적으로 기능 개발을 할 수 있다.
네이밍은 hotfix/v1.0.1 과 같은 형태로 생성한다.
Git Flow의 가장 큰 문제는 개발자가 요구하는 상황보다 더 복잡한 프로세스를 가졌다.
기계적으로 규칙을 따르기만 하면 큰 문제 없다고 하지만, 결국 복잡하기 때문에 많은 사람들이 실수하고 헤매게된다.
Github Flow는 Git Flow와 다르게 굉장히 간단한 구조이다.
개발팀이 소규모 애자일 팀이고, 제품이 단일 릴리즈 버전밖에 존재하지 않는다면 Github Flow가 적절하다. 대부분의 웹 애플리케이션은 여러 버전을 관리하지 않고, 가장 최신 버전 하나만을 사용자가 사용하게 된다.
Github Flow는 상시 배포모델로 하루에 변경사항을 작은 단위로 신속하고 자주 병합/배포 할 수 있는 구조다.
항상 Stable한 상태여야 한다.
Main의 모든 커밋은 언제 배포하든 문제 없어야하고, 언제든 브랜치를 새로 만들어도 문제가 없어야 한다. Main 브랜치의 모든 커밋은 빌드가 되고, 테스트를 통과해야한다.
이것이 Github Flow가 강제하는 유일한 사항이다.
새로운 기능을 개발할 때에는 Topic branch를 Main branch로부터 생성한다.
Git Flow의 Feature branch와 동일한 역할을 한다. 또한 별도로 Hotfix branch를 관리하지 않으며, 버그 수정도 Topic branch에서 진행한다.
이때, Topic branch의 이름은 기능을 설명하는 명확한 이름으로 네이밍 해야한다.
예를 들면, user-content-cache-key, submodules-init-task, redis2-transition 등이 있다.
Topic branch의 커밋은 기능이 완성되지 않았더라도 노트북 분실, 작업 컴퓨터의 고장등의 위험으로 코드를 지키기 위해 꾸준히 Push 한다.
사실 더 중요한 이유는 꾸준히 Push 함으로써 구성원 모두가 끊임없이 커뮤니케이션 할 수 있게 해준다.
Github에서는 PR(Pull Request)라는 유용한 기능이 존재한다.
개발자는 기능을 개발하는 중 언제든 상관없이 PR을 개설할 수 있다. 개발자들은 개설된 PR에서 토론을 하고, 코드의 특정 라인을 선택해 코멘트를 남겨 코드리뷰를 주고 받는다.
토론과 리뷰가 끝났으면, 다른 사람들의 동의(Approve)를 얻고 Main branch에 자신의 Topic branch를 merge한다.
브랜치 전략에 정해진 답은 없다.
국내에서 쉽게 접할 수 있는 자료가 Git-flow , Github-flow 두 전략 뿐이라 이 두가지만 워크플로우라고 오해하기 쉽다 (내가 그랬음) 그러나 위 nive의 글에서도 언급 되었듯이 두 워크 플로우가 정수는 맞으나 만병통치약이 될 수는 없다.
따라서 조직에 어울리는 브랜치 전략을 고안할 때 주어진 여건이 무엇인지 정확히 인지해야 한다.
현재 진행 중인 오픈소스 프로젝트(algoview)는 상대적으로 작은 규모에 팀편성이 구조적으로 이루어져있기 때문에 Github-flow를 채택하여 진행하기로 하였다.
아직 제대로 들어간 것도 안들어간 것도 아니지만... 어느 정도 깨지고 많이 배우는 시간이 되었으면, 그리고 프로젝트가 엎어지지 말았으면 좋겠다. 제발
