git
을 이용하여 수많은 서비스의 코드가 관리되고 있다. 이 git은 버전관리 시스템인 만큼, 수많은 코드를 분기별로 저장시킬 수 있고 이 분기(브랜치)별로 개인이 로컬에 들고 있을수도 있다. 특히, 이 분기를 이용하여 다양한 환경에 소스코드가 배포되도록 하는 CD를 구축할 수도 있다.
그래서 CI/CD와 이 코드의 형상관리는 큰 관계성이 있는데, git으로 원격저장소에 어떻게 배포되냐에 따른 이벤트를 이용해 이후의 자동 단계를 어떻게 구성할지 정리하고 생산성을 향상 시킬 수 있기 때문이다.
오늘 글은 우리 팀에서 쓰이는 git flow
의 여러 문제를 찾고, 그걸 어떻게 보완하려 했는지 이야기를 통해 앞으로 어떤 형태로 나아갈 것인지 이야기해보려 한다.
이 이야기를 하기 전, 메이저 전략을 사용하지 않는다고해서 실패한 전략이 아님을 이야기하고 싶다. 서비스의 크기, 특징, 구성원, 역량 등 수많은 상황은 이러한 전략을 바꿔서 적용해야하며, 이러한 브랜치 전략은 메타적으로 고려만 하면 된다. 우리는 서비스에 맞게 적용하면 된다.
초기, 우리팀은 git flow를 사용했다. (git flow가 무엇인지는 아래에서 후술한다.) 워낙 배민에서 많이 쓰고 있기도 했고, 내가 조인했을때 우리팀은 브랜치 전략을 바꾸기에 열약한 환경이었다. (iteration이 너무나 빨랐고, 폭발적으로 성장하는 비즈니스에 비해 개발자는 턱없이 부족했다.)
그렇게 정돈되지 않은 채, 서버와 프론트가 얽히며 여러 작업이 가파르게 진행되고 있었다. 가파르게 진행되다보니 여러 작업은 롤백과 급작스런 추가도 반복되었다. 갈수록 git flow는 장점을 잃어갔다.
우리 팀에서 제작하던 B마트는 빈번한 배포를 통해 사용자의 가치를 끊임없이 제공하는 커머스 서비스였고, git flow의 수많은 브랜치는 신규/기존 입사자 상관없이 히스토리를 commit 상으로 해석하기 매우 어려웠다.
주마다 배포가 진행된 다음 오후에 백포팅이 진행되는데, 백포팅이 진행되면 거의 무조껀 컨플릭트는 일어났고, 가끔씩 변동사항이 너무 크면 다들 모여서 노트북 하나로 돌아가면서 컨플릭트를 고치고 develop에 force-push를 빈번히 했다.
정신없이 진행되던 한달 동안, 프론트엔드의 코드 베이스는 급속도로 커져갔고 이러한 문제를 프론트만이라도 분리하고 싶었다. 왜냐하면 추후 들어올 개발자가 히스토리 파악하는 고통을 겪게 하고 싶지 않았기 때문이었다.
그래서 프론트엔드 소스코드와 백앤드의 의존도를 분리시키는 작업을 진행했고, 진행 후 새로운 레포지토리에 코드를 테라포밍했다. 테라포밍 후 나는 브랜치 전략을 새로 확립하게 된다. 어떻게 확립했는지 설명하기위해 git flow에 대해서 설명한다.
가장 유명한 방법론인 "git flow"는 2010년 빈센트 드리슨이 창안했다. 여기서 가장 중요한 두 개의 브랜치는 다음과 같다.
개발주기 (해당 프로젝트의 개발사항이 운영에 반영되어야 하는 개발 일정) 동안 develop, main 브랜치를 기준으로 여러 브랜치가 파생된다.
이러한 git flow의 장점은 명확하게 요소들이 어떤 역할을 하는지 오랜시간에 걸쳐 규칙적으로 개발자들에게 내려져 온 만큼 수많은 툴들이 존재하며, 이 수많은 툴로 하여금 git flow는 쉽게 운영할 수 있다는 것에 있다. 또한 CI/CD에 디펜던시 되어있지 않기 때문에 철학적으로만 집중할 수 있으며, DevOps가 없는 스타트업이나 목표가 명확한 SI등의 업체에서 자동화를 하지 않고 수동으로 해당 전략을 사용할 수도 있다.
git flow는 main의 버전이 태그단위로 운용된다. 그래서 롤백을 진행할 때 tag로 하여금 빠르게 롤백할 수 있도록 제공한다. 그렇기에 우리 비즈니스상 배포가 되는 것은 결국 하나이므로, main 전략은 유지해도 되었다. 문제는 이 전의 release와 develop이었다. git flow 전략에서 release는 하나만 존재한다. develop에 완료된 기능을 release에 태우고, release에서 테스트한다. (보통 담당하는 QA 분들이 있을 것이다. 혹은 기획자라도.) 운영으로 나가기 이 전에 테스트를 release에서 진행하는데, 상황을 한 가지 예시를 들어보겠다.
B마트의 비즈니스는 매 주 배포가 빈번히 나가며, 심지어 매주 두 번 나갈수도 있고, 그 이상 나갈수도 있다. 그런데 이 배포의 사이즈가 일관적이지 않으며 이번주는 작지만, 다음주엔 큰 배포건이 있을수도 있다는 것이다. 이번주에 나가기 위해 저번주에 release로 develop에 있는 내용을 옮겼다. 그렇게 release를 배포를 진행했는데 다음주에 배포가 진행되는 건이 사이즈가 커서 저번주에 함께 나갔었다.
이러한 상황에서 release는 온전히 main으로 머지될 수 있는가? 여기서 release branch는 테스트 배포를 위한 브랜치 목적으로 사용되었는데, 온전히 main으로 병합될 수 없으므로 release에서 cherry-pick이든 후속처리를 통해 main으로 가야한다. 그렇기에 B마트의 비즈니스상 릴리즈 브랜치가 여러개 존재할 수 밖에 없고, 이는 git flow와 다른 양상으로 흐르게 된다.
그래서 B마트 프론트는 release/v1.6.0 형태로, 배포 번호를 매겨 그 주에 배포될 건을 매칭시켰다. 이를 지라의 릴리즈 노트와 연결시켜 기획, QA와 싱크업을 진행했다. 그렇게 언제 어떤 작업이 나가는지 기획은 릴리즈 노트와 티켓의 현황을 확인하면 되고, 개발자는 티켓을 작성하고 릴리즈 노트에 연결시킨 후, release 브랜치 기준으로 작업이 진행되었다.
이렇게 되니 개발과 기획이 싱크업이 편해졌으며, 여러 release 버전에 대해 사전에 만들어두기만 하면 쉽게 대응 할 수 있게 변경되었다. 다시 이야기로 돌아와서, 문제라고 언급했던 두 릴리즈의 테스트는 아래와 같이 제공했다.
커뮤니케이션만 진행되면 문제는 발생하지 않는다. 음. 근데 커뮤니케이션만 진행되면? 커뮤니케이션이 안되면 무슨 참사가 일어나는걸까?
커뮤니케이션이 안되었다고 이러한 큰 혼란이 일어나는 이유는, 릴리즈들은 main 혹은 develop 기준으로 만들어졌기 때문에 이후 release와 이전 release가 서로간 작업이 배포되지 않는 한 공유가 되지 않는다.
release가 어떻게 붙었든, 결국 작업은 동일하고 배포를 어디에, 언제 하는지만 다른건데 왜 우리는 두 작업이 서로 나뉘어져 있어서 "커뮤니케이션"을 통해 테스트를 잡아야하는 환경이 된 걸까?
이는 git flow의 너무 많은 정책때문에 그렇다. 매주 빈번하게 나가는 서비스는 git flow의 수많은 브랜치를 거치지 않으면서 유동적으로 배포될 수 있어야 한다. develop, release, main이 필요없다는 소리이다. develop을 삭제하고 main을 기점으로 release만 반복하면 된다. 배포는 tag를 기준으로 나누면 된다.
develop을 삭제하면 아래와 같은 이점을 얻을 수 있다.
어느정도 팀이 안정되고 대규모 개발이 일어나서 빈번한 배포가 일어날때, git flow는 장점이 퇴색된다. 많은 브랜치는 신경써야할 부분을 크게 늘리며, 자동화를 하기 까다롭게 만든다. 그렇기 때문에 이를 더 단순화시킨 gitlab flow, github flow등이 존재한다.
gitlab flow는 기능 중심 개발 방법과 이슈 트래킹 시스템에 연계되는 기능 개발 브랜치를 합친 개념이다. 쉽게 이야기하면 위에서 언급한 feature 단위의 개발 방법을 이슈 트래킹 시스템과 연동시켜, 단순하고 빠르게 git 작업을 진행할 수 있게한다.
gitlab flow는 git flow의 복잡한 여러 브랜치에서, 단순히 배포로 가기위한 과정을 목표로 축약한 개념이다.
결국 develop과 master의 분리가 필요없는게, 코드는 다 가지고 있고 언제 뭐가 배포되는지만 신경쓰면 되는 것이다. 관점이 다른데, git flow는 "개발"이 주 목적이지만, gitlab flow는 "배포"가 중심에 있다. 그렇기 때문에 배포 전용 branch가 존재하고, 이 브랜치에서 히스토리를 전부 관리할 수 있다. 또한 다양한 배포가 진행되면서 배포가 된 것인지 확인을 쉽게할 수 있는 장점이 있다.
CI/CD 관점에서도 gitlab flow는 용이한데, pre-production에 배포되면 무조껀 jenkins나 배포 툴에서 배포되도록 하면 된다. 운영도 동일하다. 하지만, 이와 같이 단방형으로 잘 운영되려면 단순한 만큼 테스트가 철저해야한다는 점이 중요하다.
gitlab flow는 git flow에 비해서 축약된 만큼 여러 규칙이 존재한다. GitLab의 CEO인 Sid Sijbrandij는 11가지 규칙에 대해서 이야기 한 바가 존재한다.
가장 중요한 이야기는, 테스트하라는 내용이 많은 것처럼, 테스트는 무조껀 필수적인 사항이다. gitlab flow를 적용했다고 이야기하려면 CI/CD등의 자동화도 이루어져야 하지만, 테스트 코드부터 커버리지를 높혀야한다.
서비스가 점점 커져감에따라, 지금은 B마트 뿐아니라 커머스 전체를 커버하게되면서 자동화된 브랜치 전략, 자동화된 배포 등이 필요해졌다. git flow는 자동화하기 어렵고, 브랜치를 관리하기도 규모가 커짐에따라 어려워진다.
특히나 최근의 웹 프론트는 monorepo로 회사들이 전환하고 있다. monorepo에서 수많은 개발자가 수많은 요구사항에 대한 반영을 진행하며 폭발적으로 커지면 git flow로는 커버할 수가 없는 지점에 도착하게 된다. 서비스 규모가 커지기 전에 CI/CD를 구축해야하며, 구축하기 전 테스트 커버리지를 틈틈히 올리고 git branch 전략을 심플하게 전환시켜야 한다.