들어가며: 왜 브랜치 전략이 중요한가

이전 글에서 Git의 기본 개념과 GitHub 저장소 생성에 대해 알아보았습니다. 이번에는 실제 팀 프로젝트에서 가장 중요한 요소 중 하나인 브랜치 전략에 대해 깊이 있게 살펴보겠습니다.

혼자 개발할 때는 별 문제 없던 것들이 팀원이 늘어나면 복잡해지기 시작합니다. "누가 어떤 기능을 개발하고 있지?", "이 코드 왜 갑자기 바뀌었어?", "배포 전에 급하게 버그를 고쳐야 하는데 어떻게 하지?" 같은 상황들이 빈번하게 발생하죠. 바로 이런 문제들을 해결하기 위해 브랜치 전략이 필요합니다.

잘 설계된 브랜치 전략은 팀원 간의 충돌을 최소화하고, 배포 프로세스를 체계화하며, 코드 품질을 유지하는 데 핵심적인 역할을 합니다. 지금부터 브랜치의 기본 개념부터 실무에서 널리 사용되는 전략들까지 하나씩 알아보겠습니다.

1. 브랜치란 무엇인가

1.1 브랜치의 개념

브랜치(Branch)는 말 그대로 '가지'라는 의미입니다. 나무 줄기에서 여러 가지가 뻗어 나가듯이, 하나의 코드베이스에서 여러 개의 독립적인 작업 흐름을 만들 수 있습니다.

브랜치를 사용하면 메인 코드에 영향을 주지 않고 새로운 기능을 개발하거나 버그를 수정할 수 있습니다. 작업이 완료되면 다시 메인 코드에 병합(merge)하는 방식으로 협업이 이루어집니다.

브랜치는 특정 커밋을 가리키는 포인터입니다. 새로운 브랜치를 만든다는 것은 현재 위치에서 새로운 포인터를 생성하는 것이며, 이후 각 브랜치에서의 커밋은 해당 브랜치의 포인터만 이동시킵니다.

1.2 브랜치가 필요한 이유

브랜치 없이 작업한다고 상상해 보세요. 모든 팀원이 하나의 코드 위에서 동시에 작업하면 어떤 일이 벌어질까요?

  • 코드 충돌 빈발: 같은 파일을 여러 명이 수정하면 충돌이 자주 발생합니다.
  • 불완전한 코드 배포: 개발 중인 기능이 실수로 배포될 수 있습니다.
  • 롤백의 어려움: 문제가 생겼을 때 특정 기능만 되돌리기가 어렵습니다.
  • 병렬 작업 불가: 한 사람이 작업을 끝낼 때까지 다른 사람이 기다려야 합니다.

브랜치를 사용하면 이러한 문제들을 자연스럽게 해결할 수 있습니다. 각자 독립된 공간에서 작업하고, 완성된 것만 합치면 되니까요.

2. 브랜치 기본 명령어

2.1 브랜치 생성과 조회

가장 기본적인 브랜치 관련 명령어들을 살펴보겠습니다.

# 현재 브랜치 목록 확인
git branch

# 원격 브랜치 포함 모든 브랜치 확인
git branch -a

# 새 브랜치 생성 (현재 브랜치에서 분기)
git branch feature/login

# 브랜치 생성과 동시에 이동
git checkout -b feature/login

# 또는 최신 방식으로
git switch -c feature/login

2.2 브랜치 이동: checkout vs switch

Git 2.23 버전부터 switch 명령어가 도입되었습니다. 기존 checkout은 브랜치 이동 외에도 파일 복원 등 여러 기능을 담당했는데, 이를 분리하여 직관성을 높인 것입니다.

# 기존 방식 (여전히 사용 가능)
git checkout feature/login

# 새로운 방식 (권장)
git switch feature/login

# 이전 브랜치로 돌아가기
git switch -

개인적으로는 switch 명령어를 더 권장합니다. 용도가 명확하고, 실수로 파일을 덮어쓰는 일을 방지할 수 있거든요.

2.3 브랜치 병합 (Merge)

작업이 완료된 브랜치를 다른 브랜치에 합치는 것을 병합(merge)이라고 합니다.

# main 브랜치로 이동
git switch main

# feature/login 브랜치를 main에 병합
git merge feature/login

# 병합 완료 후 브랜치 삭제 (선택사항)
git branch -d feature/login

2.4 브랜치 삭제

# 병합된 브랜치 삭제
git branch -d feature/login

# 병합되지 않은 브랜치 강제 삭제 (주의 필요)
git branch -D feature/experimental

# 원격 브랜치 삭제
git push origin --delete feature/login

3. Git Flow 전략

3.1 Git Flow란

Git Flow는 2010년 Vincent Driessen이 제안한 브랜치 전략으로, 대규모 프로젝트에서 널리 사용됩니다. 명확한 규칙과 구조를 가지고 있어 팀원 모두가 일관된 방식으로 작업할 수 있습니다.

3.2 Git Flow의 브랜치 종류

메인 브랜치 (항상 유지)

  • main (또는 master): 프로덕션에 배포되는 코드만 존재합니다. 모든 커밋에는 버전 태그가 붙습니다.
  • develop: 다음 릴리스를 위한 개발이 진행되는 브랜치입니다. feature 브랜치들이 여기로 병합됩니다.

보조 브랜치 (필요시 생성 후 삭제)

  • feature/*: 새로운 기능 개발용. develop에서 분기하고, develop으로 병합됩니다.
  • release/*: 릴리스 준비용. develop에서 분기하고, main과 develop 양쪽에 병합됩니다.
  • hotfix/*: 긴급 버그 수정용. main에서 분기하고, main과 develop 양쪽에 병합됩니다.

3.3 Git Flow 실제 사용 예시

# 1. 새 기능 개발 시작
git switch develop
git switch -c feature/user-authentication

# 2. 기능 개발 완료 후 develop에 병합
git switch develop
git merge --no-ff feature/user-authentication
git branch -d feature/user-authentication

# 3. 릴리스 준비
git switch -c release/1.0.0 develop

# 4. 릴리스 브랜치에서 마지막 수정 후 main에 병합
git switch main
git merge --no-ff release/1.0.0
git tag -a v1.0.0 -m "Version 1.0.0"

# 5. develop에도 병합
git switch develop
git merge --no-ff release/1.0.0
git branch -d release/1.0.0

# 6. 긴급 버그 수정 (hotfix)
git switch main
git switch -c hotfix/critical-bug

# 7. 수정 후 main과 develop 양쪽에 병합
git switch main
git merge --no-ff hotfix/critical-bug
git tag -a v1.0.1 -m "Hotfix: critical bug"
git switch develop
git merge --no-ff hotfix/critical-bug
git branch -d hotfix/critical-bug

3.4 Git Flow의 장단점

장점

  • 명확한 규칙으로 대규모 팀에서도 일관성 유지
  • 릴리스 버전 관리가 체계적
  • 프로덕션과 개발 코드가 명확히 분리
  • 긴급 수정에 대한 명확한 프로세스 제공

단점

  • 브랜치가 많아 복잡할 수 있음
  • 빈번한 배포(CI/CD)에는 적합하지 않음
  • 소규모 프로젝트에는 과도한 오버헤드

4. GitHub Flow 전략

4.1 GitHub Flow란

GitHub Flow는 Git Flow의 복잡성을 줄인 단순하고 효율적인 전략입니다. GitHub에서 제안했으며, CI/CD 환경에 최적화되어 있습니다.

4.2 GitHub Flow의 규칙

  1. main 브랜치는 항상 배포 가능한 상태 유지
  2. 새로운 작업은 main에서 브랜치를 만들어 시작
  3. 브랜치 이름은 설명적으로 작성 (예: feature/add-login, fix/header-bug)
  4. 작업 중 자주 원격에 push하여 백업
  5. 준비가 되면 Pull Request 생성
  6. 코드 리뷰 후 main에 병합
  7. 병합 즉시 배포

4.3 GitHub Flow 실제 사용 예시

# 1. main에서 새 브랜치 생성
git switch main
git pull origin main
git switch -c feature/shopping-cart

# 2. 작업하면서 자주 커밋
git add .
git commit -m "Add cart item component"
git push origin feature/shopping-cart

# 3. 추가 작업
git add .
git commit -m "Implement cart total calculation"
git push origin feature/shopping-cart

# 4. GitHub에서 Pull Request 생성
# (웹 인터페이스 또는 gh CLI 사용)

# 5. 리뷰 완료 후 main에 병합 (보통 GitHub 웹에서 수행)

# 6. 로컬 정리
git switch main
git pull origin main
git branch -d feature/shopping-cart

4.4 GitHub Flow의 장단점

장점

  • 매우 단순하고 이해하기 쉬움
  • 지속적 배포(CD)에 적합
  • 소규모 팀에 이상적
  • 빠른 피드백 사이클

단점

  • 릴리스 버전 관리가 명시적이지 않음
  • 여러 버전을 동시에 유지해야 할 때 적합하지 않음

5. Trunk Based Development

5.1 Trunk Based Development란

Trunk Based Development(TBD)는 모든 개발자가 하나의 브랜치(trunk 또는 main)에서 직접 작업하는 방식입니다. Google, Facebook 등 대형 테크 기업에서 사용합니다.

5.2 핵심 원칙

  • 짧은 수명의 브랜치: 브랜치는 하루 이내에 병합
  • 작은 단위의 커밋: 큰 기능도 작게 나누어 자주 커밋
  • Feature Flag 활용: 완성되지 않은 기능은 플래그로 숨김
  • 강력한 테스트 자동화: 모든 커밋에 대해 자동 테스트 실행

5.3 Feature Flag 예시

// 완성되지 않은 기능을 플래그로 제어
const FEATURES = {
  newCheckout: false,  // 아직 개발 중
  darkMode: true       // 출시됨
};

function renderCheckout() {
  if (FEATURES.newCheckout) {
    return <NewCheckout />;
  }
  return <OldCheckout />;
}

5.4 TBD의 장단점

장점

  • 머지 충돌 최소화
  • 지속적 통합(CI)에 최적화
  • 코드 통합이 빈번하여 문제 조기 발견

단점

  • 높은 수준의 테스트 자동화 필요
  • Feature Flag 관리 복잡도 증가
  • 팀원들의 높은 역량과 규율 필요

6. 브랜치 전략 선택 가이드

6.1 프로젝트 규모별 추천

프로젝트 유형 추천 전략 이유
1-2인 소규모 프로젝트 GitHub Flow 단순하고 빠름
스타트업 (5-10인) GitHub Flow 빠른 반복과 배포에 적합
중규모 팀 (10-30인) Git Flow 또는 변형 체계적인 릴리스 관리 필요
대규모 조직 Git Flow 또는 TBD 명확한 규칙 또는 강력한 자동화 필요
오픈소스 프로젝트 GitHub Flow 외부 기여자의 PR 처리에 적합

6.2 배포 주기별 추천

  • 매일 또는 수시 배포: GitHub Flow, TBD
  • 주간 또는 스프린트 단위 배포: GitHub Flow, Git Flow 단순화 버전
  • 월간 또는 분기별 릴리스: Git Flow

7. 머지 충돌 해결하기

7.1 머지 충돌이 발생하는 이유

두 브랜치에서 같은 파일의 같은 부분을 서로 다르게 수정했을 때 Git은 어떤 변경사항을 유지해야 할지 스스로 판단할 수 없습니다. 이때 충돌(conflict)이 발생하고, 개발자가 직접 해결해야 합니다.

7.2 충돌 해결 과정

# 병합 시도
git merge feature/login
# CONFLICT (content): Merge conflict in src/App.js

# 충돌 파일 확인
git status

# 충돌 파일을 열면 다음과 같이 표시됨
# <<<<<<< HEAD
# const title = "Welcome";
# =======
# const title = "Hello World";
# >>>>>>> feature/login

충돌 마커를 이해하면 해결이 쉬워집니다:

  • <<<<<<< HEAD: 현재 브랜치(병합 대상)의 내용
  • =======: 구분선
  • >>>>>>> feature/login: 병합하려는 브랜치의 내용

7.3 충돌 해결 및 완료

# 1. 파일을 직접 편집하여 최종 코드 작성
# 충돌 마커를 모두 제거하고 원하는 코드만 남김

# 2. 해결된 파일을 스테이징
git add src/App.js

# 3. 병합 커밋 생성
git commit -m "Merge feature/login: resolve conflict in App.js"

# 또는 병합 취소
git merge --abort

7.4 충돌 예방 팁

  • 자주 pull 받아 최신 상태 유지
  • 브랜치 수명을 짧게 유지
  • 큰 파일보다는 작은 파일 여러 개로 분리
  • 팀원과 작업 영역 조율

8. Rebase vs Merge

8.1 Merge의 특징

Merge는 두 브랜치의 히스토리를 그대로 유지하며 합칩니다.

git switch main
git merge feature/login

장점

  • 히스토리가 정확하게 보존됨
  • 작업 맥락을 이해하기 쉬움
  • 안전하고 되돌리기 쉬움

단점

  • 히스토리가 복잡해질 수 있음
  • 불필요한 머지 커밋이 많아질 수 있음

8.2 Rebase의 특징

Rebase는 커밋들을 다른 브랜치 위로 "재배치"합니다. 마치 처음부터 그 브랜치에서 작업한 것처럼 히스토리가 만들어집니다.

# feature 브랜치에서 main의 최신 내용 위로 재배치
git switch feature/login
git rebase main

# main에서 fast-forward 병합
git switch main
git merge feature/login

장점

  • 깔끔한 선형 히스토리
  • 불필요한 머지 커밋 없음
  • 코드 리뷰 시 변경사항 추적이 쉬움

단점

  • 히스토리가 변경되므로 주의 필요
  • 이미 push한 브랜치에는 사용 자제
  • 충돌 해결이 여러 번 필요할 수 있음

8.3 언제 무엇을 사용할까

상황 추천
로컬에서만 작업한 브랜치 정리 Rebase
이미 원격에 push한 브랜치 Merge
공유 브랜치 (main, develop) Merge
feature 브랜치 최신화 Rebase (push 전)
팀 규칙이 있는 경우 팀 규칙을 따름
황금률: "공개(push)된 히스토리는 rebase하지 않는다." 다른 사람이 기반으로 사용 중인 커밋을 rebase하면 큰 혼란이 발생합니다.

마무리: 브랜치 전략은 팀 문화다

지금까지 브랜치의 기본 개념부터 다양한 브랜치 전략, 그리고 충돌 해결 방법까지 살펴보았습니다. 어떤 전략이 "정답"이라고 말하기는 어렵습니다. 중요한 것은 팀의 상황에 맞는 전략을 선택하고, 모든 팀원이 동일한 규칙을 따르는 것입니다.

처음에는 단순한 GitHub Flow로 시작하고, 프로젝트가 커지면서 필요에 따라 규칙을 추가해 나가는 것도 좋은 방법입니다. 브랜치 전략은 한 번 정하면 끝이 아니라, 팀과 프로젝트가 성장하면서 함께 진화해야 합니다.

다음 편에서는 Pull Request와 코드 리뷰에 대해 알아보겠습니다. 브랜치 전략을 실제로 운영하는 데 있어 PR과 코드 리뷰는 필수적인 요소이니, 꼭 함께 읽어보시기 바랍니다.