Git 브랜치 전략
"A branching strategy is a convention, or a set of rules, that developers follow to write, merge, and deploy code in a version control system."
— 엔터프라이즈 애자일 개발 거버넌스 프레임워크에 서술된 가이드.
교과서대로 Git Flow를 엄격히 쓰겠다며 온갖 엄숙함을 다 떨었지만, 결국 급작스러운 실운영 장애 앞에 룰을 다 깨부수고 master에 직접 push --force를 때려 박는 현실. 전략 이름은 중요하지 않다. 옆 자리 동료가 내가 고치는 파일을 건드리지 않고 제발 휴가를 떠나주기를 바라는 간절한 소망이 전부다
1. 개요
Git 브랜치 전략은 분산 버전 관리 시스템(Git)을 사용할 때 여러 명의 개발자가 소스코드를 안전하고 효율적으로 병합하며 릴리스하기 위한 작업 흐름 규약(Workflow Protocol)이다. Git의 '브랜치 따기(Branching)'는 물리적 비용이 제로에 가깝기 때문에 누구나 평행 우주를 밥 먹듯이 만들 수 있다. 그러나 이 평행 우주들을 다시 하나로 합쳐서 출시할 때, 아무런 규칙이 없다면 서로 남의 코드를 덮어쓰고 버그가 가득한 코드가 상용 서버로 유출되는 대재앙이 일어난다.
이러한 교통사고를 방지하기 위해 업계에서는 '배포 가능한 코드(main/master)는 여기서 지키고, 개발 중인 코드(develop)는 여기서 합치며, 각자 만드는 신기능(feature)은 따로 떼서 작업하자'라는 일종의 국경선과 교통 신호등을 구축했다. 서비스의 성격, 팀의 규모, 그리고 CI/CD 자동화 수준에 따라 최적의 전략이 다르다.(...)
2. 전통의 장엄한 교과서, Git Flow
2.1. 5개 브랜치로 지키는 완벽한 국경선
네덜란드의 소프트웨어 엔지니어 빈센트 드라이센이 2010년에 창안한 가장 유구하고 강력한 브랜치 모델이다. 엄격한 역할 분담을 가진 5종류의 브랜치를 운영한다.
- master(main): 언제든 유저가 사용할 수 있는, 버그가 0%여야 하는 완벽한 실운영 배포용 브랜치.
- develop: 다음 버전을 향해 달려가는 개발 전선이자 중심 줄기 브랜치. 개발자들의 코드가 최초로 합쳐지는 아수라장이다.
- feature: 새로운 기능 하나를 짜기 위해 develop에서 가지를 쳐서 나오는 브랜치. 작업이 끝나면 develop으로 머지된다.
- release: 다음 메이저 릴리스를 배포하기 전, develop에서 분기하여 막바지 QA(품질 테스트)와 자잘한 버그 픽스만을 전담하는 임시 브랜치. 테스트가 끝나면 master와 develop 양쪽으로 동시에 머지된다.
- hotfix: 이미 배포된 master 코드에 치명적인 보안 구멍이나 심각한 장애가 터졌을 때, 수술실 침대처럼 긴급 분기하여 땜질한 뒤 다시 master와 develop에 찔러 넣는 긴급 수리 브랜치.
이 전략은 정기적인 배포 주기가 뚜렷하고 패키지 소프트웨어처럼 버전 관리가 엄격해야 하는 대형 프로젝트에서 철벽 방어를 선사한다. 단, 배포 주기 한 번에 feature 브랜치 수십 개를 한 번에 들이미는 날에는 눈물 없이는 볼 수 없는 머지 컨플릭트 대축제가 벌어진다.1
3. 단순함과 민첩함의 상징, GitHub Flow와 Trunk-based
3.1. GitHub Flow (깃허브 플로우)
GitHub 팀이 고안한 극단적으로 단순한 전략이다. 웹 서비스처럼 하루에도 수십 번씩 무중단 배포를 때리는 애자일 팀에 최적화되어 있다.
- 오직 main 브랜치와 feature 브랜치 단 둘만 존재한다.
- 신기능을 만들 때는 무조건 main에서 feature 브랜치를 파고, 완성되면 Pull Request(PR)를 올린다.
- 동료들의 엄밀한 코드 리뷰를 통과하면 그 즉시 main으로 머지하고, 그 즉시 서버에 배포한다.
중간에 'develop'이나 'release' 같은 정거장이 없기 때문에 개발 속도가 우주선처럼 빠르지만, 만에 하나라도 main이 오염되면 그 즉시 실운영 서버가 사망하므로 탄탄한 테스트 자동화(CI/CD)가 구비되지 않은 오합지졸 팀이 이를 도입하면 매일매일이 재앙의 연속이 된다.(...)
3.2. 트렁크 기반 개발 (Trunk-based Development)
구글, 메타 같은 실리콘밸리 빅테크 기업들이 애용하는 아키텍처다. 개발자들이 며칠씩 브랜치를 묵혀두지 않고, 모든 개발자가 오직 하나의 Trunk(main) 브랜치에 매일매일 코드를 바로 밀어 넣는다.
브랜치가 하나뿐이니 머지 충돌 자체가 일어날 틈이 없지만, 미완성된 기능도 메인 브랜치에 바로 들어가게 되므로, 릴리스 상태를 제어하기 위해 코드 레벨에서 기능을 동적으로 켜고 끄는 '피처 토글 (Feature Toggle)' 기술을 반드시 연동해서 써야 하는 고인물 전용 하이테크 전략이다.2
4. 관련 밈 및 드립
4.1. Pull Request 'Approve 부탁드립니다'의 눈물
Git 브랜치 전략의 필수 의식인 Pull Request(PR). 동료의 Approve(승인)를 받아야 메인 브랜치에 내 코드를 얹을 수 있다. 그러나 다들 자기 업무에 치여 PR 목록을 구석에 박아두고 방치하기 일쑤다. 결국 내 코드가 메인 코드와 너무 동떨어져 썩어가는(Stale) 광경을 본 개발자는, 슬쩍 동료의 자리 옆으로 기어가 커피 한 잔을 쥐여주며 "제발 사장님 한 번만 눌러주세요"라고 비굴하게 애원하는 구걸 모드로 전입하곤 한다.(...)
5. 여담
- 창시자의 솔직한 반성: Git Flow의 창시자 빈센트 드라이센은 2020년, 자신의 원본 글 최상단에 "10년 동안 웹 서비스가 대세가 되었으므로, 매일 배포하는 현대 웹 애플리케이션의 경우 굳이 복잡한 Git Flow를 쓰지 말고 단순한 GitHub Flow를 쓸 것을 강력히 권장한다"는 일침 섞인 업데이트를 남겨 스스로의 룰을 격하시켰다.
- Trunk-based의 무시무시함: 구글은 수만 명의 엔지니어가 하나의 메인 모노레포(Monorepo) 코드 트렁크에 매일 4만 번 이상의 커밋을 때려 박는다. 빌드와 테스트 파이프라인의 엄청난 리소스가 이를 받쳐주지 않으면 실시간으로 인프라가 녹아내릴 작업 밀도다.
- Rebase vs Merge의 종교 전쟁: 브랜치를 합칠 때 깔끔한 한 줄 히스토리를 만들기 위해 기존 커밋을 죄다 뜯어고쳐 이어 붙이는
Rebase파와, 삐뚤빼뚤 꼬불꼬불해도 역사적 팩트를 다 보존해야 한다는 정통Merge파 사이의 키보드 배틀은 백엔드 포럼에서 절대로 꺼지지 않는 영원불멸의 화약고다.