TL;DR
- Git flow의
develop/release/feature계층이 소규모 팀에 과했고, 정기 배포 주기 탓에 리드타임이 길었습니다.- trunk 기반 개발로 바꾸면서 짧은 브랜치 + 하루 안에 머지되는 작은 PR, 그리고 직접 만든 가벼운 피처 플래그를 도입했습니다.
- 배포는 체감상 확연히 빨라졌고 소규모 팀에 잘 맞았습니다. 다만 trunk가 모든 상황의 정답은 아닙니다.
결론부터 말하면, 우리 팀에 Git flow는 과한 전략이었습니다.
Git flow는 2010년 Vincent Driessen이 정리한 브랜치 모델입니다. main, develop, feature/*, release/*, hotfix/*로 역할을 나눠 릴리스 관리를 체계화합니다. 잘 만든 모델이고, 한때 사실상 표준처럼 쓰였습니다.
문제는 우리 상황이 그 모델이 가정한 상황과 달랐다는 점입니다. 흥미롭게도 Driessen 본인도 2020년에 글 상단에 노트를 덧붙였습니다. "웹 앱처럼 지속적으로 배포하고 롤백하지 않으며 여러 버전을 동시에 유지하지 않는 소프트웨어라면, git-flow 대신 훨씬 단순한 워크플로를 쓰라"는 취지였습니다. 우리가 만드는 게 정확히 그런 웹 앱이었습니다.
구체적으로 두 가지가 아팠습니다.
release 브랜치를 따고 정기 배포 주기에 맞춰 내보내다 보니, 다 만든 기능이 며칠씩 develop에 고여 있었습니다. 리드타임(코드 작성 → 실제 배포)이 길어졌습니다.develop과 release를 따로 관리하느라, 정작 코드보다 브랜치를 신경 쓰는 시간이 늘었습니다.trunk 기반 개발(trunk-based development)은 단순합니다. 모두가 하나의 trunk(main)를 공유하고, 짧게 산 브랜치를 자주 머지합니다. DORA 연구에서도 짧은 브랜치(보통 하루 미만)와 최소 하루 한 번 이상의 머지를 권장하고, 엘리트 퍼포머가 trunk 기반을 채택할 확률이 그렇지 않은 팀의 2.3배라고 보고합니다.
다만 브랜치 복잡도를 줄인 대가로, 다른 두 가지를 새로 들여야 했습니다.
가장 먼저 바꾼 건 PR 크기와 리뷰 속도였습니다. 브랜치를 길게 끌면 trunk 기반의 장점이 사라지고 오히려 머지 충돌만 커집니다. 그래서 규칙을 단순하게 잡았습니다.
작은 PR은 리뷰어의 부담도 작아서, 리뷰가 빨라지고 머지가 빨라지는 선순환이 생겼습니다.
여기서 자연스럽게 질문이 생깁니다. "기능이 아직 안 끝났는데 main에 머지하면, 미완성 코드가 배포되는 것 아닌가?"
이걸 푸는 게 피처 플래그입니다. 미완성 기능을 플래그 뒤에 숨겨두고, 코드는 trunk에 들어가되 사용자에게는 노출되지 않게 합니다. LaunchDarkly·Unleash 같은 전문 도구도 있지만, 우리는 규모에 맞게 환경변수 기반으로 직접 만들었습니다.
// flags.ts — 환경변수로 켜고 끄는 가장 단순한 플래그 const FLAGS = { newCheckout: process.env.NEXT_PUBLIC_FLAG_NEW_CHECKOUT === 'true', } as const; export function isEnabled(flag: keyof typeof FLAGS): boolean { return FLAGS[flag]; }
// 사용하는 쪽 — 미완성 기능을 플래그 뒤에 숨긴다 import { isEnabled } from '@/lib/flags'; export function Checkout() { if (isEnabled('newCheckout')) { return <NewCheckout />; // 아직 개발 중, 플래그 꺼두면 안 보임 } return <LegacyCheckout />; }
별도 SaaS 없이도 "trunk에는 머지하되, 노출은 환경변수로 통제한다"는 핵심은 충분히 굴러갔습니다. 기능이 완성되면 플래그를 켜고, 안정화되면 분기 코드를 지우는 흐름입니다.
전환 후 배포가 체감상 확연히 빨라졌습니다. 다 만든 기능이 release 브랜치를 기다리지 않고 그날그날 trunk로 들어가니, 리드타임이 짧아졌습니다. 브랜치를 신경 쓰는 정신적 비용도 줄었습니다. 소규모 팀에는 잘 맞는 선택이었고, 대체로 만족합니다.
물론 공짜는 아니었습니다. 플래그를 켜고 끄는 책임이 생기고, 다 쓴 플래그를 제때 지우지 않으면 코드에 분기가 쌓입니다. "도입보다 정리가 중요하다"는 걸 전환하고 나서 배웠습니다.
trunk 기반은 자주 배포하는 웹 앱, 그리고 브랜치 계층을 관리할 여력보다 빠른 흐름이 중요한 소규모 팀에 특히 잘 맞습니다. 반대로 긴 QA 사이클이나 여러 버전을 동시에 유지·지원해야 하는 제품이라면, Git flow의 release 계층이 여전히 의미가 있을 수 있습니다. Driessen이 2020년에 남긴 노트도 결국 "맥락에 맞게 고르라"는 이야기였습니다.