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

코드베이스 도구는 요즘 대부분 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 전략에 관한 내용입니다. Branch 전략 중 Git flow vs Changes 방법을 비교하였습니다.

Git Branch 전략

Git branch 전략은 유명한 Git flow(참고1)이 있습니다. 저는 회사 내의 규제/제한으로 인해서 Git flow를 변형한 전략을 사용하고 있습니다. 일반적으로 프로젝트 설정 시 Git Branch 전략을 세울 때 고려할 점을 정리하였습니다.

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

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

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

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

Git flow

Git flow는 이미 너무 유명한 방법입니다. Git Branch 전략으로 많은 사람들이 선택하고 있으며 도구(git-flow 등)도 깔끔하게 만들어져 활용하기 좋습니다. Git Flow 전략을 살펴보면 다음과 같습니다. (참고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 원칙은 없지만 코드베이스의 목적인 코드 저장 및 공유를 하면서 ‘코드 품질, 코드 가독성(검색)‘을 높여주는 전략을 고민하면 좋겠습니다.