프로젝트를 시작할 때 기본적으로 논의하는 '코드베이스', '코드리뷰', '배포방안' 중 코드베이스 관리에 관련한 고민이다.

코드베이스 도구는 요즘 대부분 git으로 선택한다. TFS(Team Foundation Server), Subversion, CVS, Git 등 많은 코드 관리 도구 중 고민하고 선택해야 했는데 요즘엔 GitHub의 영향인지 항상 git으로 기본적으로 선택된다 (갑자기 git을 써야하는 이유에 대해서 장기간 옛회사에서 세미나를 했던 슬픈 기억이 난다). 그래도 git이 다양한 솔루션을 통해서 제공되고 코드베이스 측면에서도 '분산 버전 관리'라는 엄청난 장점이 있어서 좋다.

그리고 대중적인만큼 기본적인 Git 사용법 add, commit, stash, fetch, merge, rebase 등은 이미 많은 정보가 있고 GUI 도구(SourceTree, IntelliJ IDEA, VS Code 내장된 도구)도 매우 훌륭하다.

Git을 사용할 때 다음 요소를 고려하면 더 좋은 코드 활용/유지 보수가 가능하다고 생각한다.

  • Git Branch 전략
  • Git Message 작성 방법

그 중에서도 본 글에서는 Branch 전략에 관한 내용이다.

Git Branch 전략

Git branch 전략은 유명한 Git flow(참고[1])이 있다. 나의 경우에는 회사 내의 규제/제한으로 인해서 Git flow를 변형한 전략을 사용하고 있다.

Branch 전략을 세우는데 중요한 고려사항은 다음과 같다.

  • Branch 별 권한 (Write, Read, Pull-Request)
  • Branch 생명주기 (짧게 유지하면서 명확하게)
  • Branch 을 통한 빠른 디버깅/스냅샷 확인

위 고려사항들은 모두 코드 품질 향상, 코드 가독성(검색) 향상을 목적으로 한다. 서비스/어플리케이에서 버그가 발생하였을 때 해당 버전의 코드로 디버깅하여 원인을 찾고 상황 재현, 수정, 검증, 재배포까지의 단계를 체계적/안정적으로 처리할 수 있어야 한다.

각 단계를 효과적으로 관리하기 위한 Branch 전략 수립과 함께 Git 기능(hook, script 등)/솔루션(GitLab, Gerrit, Stash 등)을 이용하여 자동화를 구성한다. 자동화 구성은 Pull-Request, 코드 리뷰 등 코드 품질 향상을 위한 행동들을 팀 문화 혹은 절차로 대체할 수도 있다. 하지만 이런 방법은 시간에 따라 변하고 바쁠수록 무시하는 경우가 많아진다. 인간적인 측면(게으름, 나태함, 건망증 등)과 신규 인력 투입 시 실수를 최소화하는 역할로 자동화 구성이 꼭 필요하다.

그래서 처음 Branch 전략을 수립하는 시점부터 '코드 품질, 코드 가독성(검색)' 향상을 목표로 한다. 단순히 Git flow를 따라함이 아닌 현재 프로젝트 구성원, 회사의 제약 조건 등을 고려하다면 '코드 저장 관리'에서 최종 목표인 '코드 품질', '유지보수' 향상까지 제공하는 전략 수립을 도출할 수 있을 것이다.

Git flow

Git flow는 이미 너무 유명한 방법이다. 많은 사람들이 택하는 Git Flow 전략을 살펴보면 다음과 같다. (참고[1:1])

우아한 형제들의 Git-flow 전략(참고[2])이 Git Flow의 의도에 따라 사용된 좋은 예시라고 생각된다. 조금 간략하게 정리를 하면 다음과 같다.

Git flow branch 전략

Branch 목적
master 제품 출시
develop 다음 버전 개발
feature/{feature_name} 기능 개발
release 제품 출시 준비
hotfix 출시된 버전 버그 수정

개인적으로 Branch 전략을 살펴 볼 때 중요하게 체크하는 내용이 목적이다. Branch를 통해서 표현하고 싶은 의도를 명확하게 정의해야 한다. Git flow 가 좋은 점은 그 목적을 뚜렷하게 제안한다는 점이다.

Changes (by Gerrit)

※ Changes 는 별다르게 부르는 이름을 못 찾아서 적당히 붙힌 이름이다.

현재 프로젝트에서 사용하고 있는 전략은 Git-flow 와 유사하지만 feature branch는 없고 사내 코드 리뷰 도구인 Gerrit(참고[3])의 Changes로 feature 역할과 유사하게 사용하고 있다.

Changes은 Gerrit 내의 PR(Pull-Request)와 유사한 개념이다. 코드 묶음이면서 개발자가 리뷰를 남길 수 있는 공간이자 리뷰 의견을 반영한 새로운 Patchset(수정한 코드)를 추가 등록하는 공간이다.

다음은 Changes과 Patchset을 간략하게 구조화한 내용이다.

Changes
 * Patchset1: 첫번째 수정코드 <-- 개발자들이 리뷰를 남기면
 * Patchset2: 두번째 수정코드 <-- 의견을 반영한 수정 코드
 * ...N번 반복
 * PatchsetN: 최종코드 <-- 최종적으로 검토 후 Code Submit (Merge)

Changes의 최대 장점은 '빠른 생명주기'을 통해서 Branch 충돌을 최소화하고 'Branch를 간략하게' 만들어 준다는 점이다.

그리고 PR을 통한 코드 리뷰 때보다 작은 단위로 리뷰를 하게 됨으로 빠른 피드백 및 수정이 가능하다. 사실 PR도 작게 유지하면 동일한 효과를 얻을 수 있다. 그 중에서도 가장 큰 차이는 병합 시점에 Changes는 최종 Patchset이 1개의 Commit 으로 Merge or rebase가 되기 때문에 깔끔한 코드베이스 흐름을 보여준다.

Changes branch 전략

Branch 목적 특징
master 제품 출시 tag, DevOps 도구에 의해 자동 빌드 및 배포
develop 다음 버전 개발 Changes 취합, 정적 분석 및 테스트 100% 성공 시만 병합
release 제품 출시 준비 제품 Versioning, QA
hotfix 출시된 버전 버그 수정 열심히 고쳐야함!

Git flow와 Changes를 비교하면 별도의 feature가 없는 것처럼 보이지만 Gerrit 내부에서 Change 한 건마다 branch로 등록되어 관리되기 때문에 실제 동작은 feature와 동일하다. 즉 Git flow의 feature를 매번 1개의 Commit으로 rebase를 한다면 Gerrit을 이용한 코드베이스와 동일해질 것이다.

그 외 master, develop, release, hotfix branch는 git flow와 동일한 목적으로 사용한다. 현재 프로젝트에서는 개발자는 develop 브랜치만 Read/Write 권한을 가진다. Changes는 코드 리뷰 후 정적분석, 테스트, 패키징까지 수행한 뒤 원 브랜치와 병합한다.

Branch! 하지만 결국 Codebase!

Branch 전략은 어디까지나 Branch를 어떻게 사용하면 개발 생산성(판타지에나 나올법한 단어)를 높여줄 것인가에 대한 고민이다.

Git flow, changes, 개발자마다 사용하는 각자의 방법들은 매우 다양할 것이다. 사실 작은 토이 프로젝트이면 master 하나만으로도 충분한 경우가 많다. 자신의 프로젝트 성격에 따라서 Branch 전략도 적절하게 수정/변화를 주며 사용이 필요하다.

항상 프로그래밍을 하면 나오는 '그 때 그 때 달라요'는 사실 '원칙'을 기반으로 하는 달라요일 때 아름답다고 생각한다. SOLID[4] 원칙처럼 공유되는 Git branch 원칙은 없지만 코드베이스의 목적인 코드 저장 및 공유를 하면서 '코드 품질, 코드 가독성(검색)'을 높여주는 전략을 고민할 필요가 있다.


  1. 참고[1] Git flow branch model
    https://nvie.com/posts/a-successful-git-branching-model ↩︎ ↩︎

  2. 참고[2] 우아한 형제의 Git branch 전략
    http://woowabros.github.io/experience/2017/10/30/baemin-mobile-git-branch-strategy.html ↩︎

  3. 참고[3] Gerrit Code Review
    https://www.gerritcodereview.com ↩︎

  4. 참고[4] 위키백과 SOLID
    https://en.wikipedia.org/wiki/SOLID ↩︎