infra
Platform

모듈 맵

[Infra Ops] Git/GitLab 브랜치 전략과 릴리즈 관리

0 / 52 완료

펼치기
0 / 52 완료0%

Infra-ops · 34 / 52

[Infra Ops] Git/GitLab 브랜치 전략과 릴리즈 관리

Git 브랜치 전략, tag 기반 릴리즈, merge 충돌 해결, 이슈-커밋 연결까지 — 인프라 엔지니어가 알아야 할 형상관리 실무

🚨INCIDENT ALERT
HIGH

인프라 팀에서 배포 후 문제가 생겼습니다. 어젯밤 누군가 main 브랜치에 직접 push한 커밋이 있었고, 오늘 오전 배포에서 그 코드가 올라갔습니다. 롤백 요청이 왔는데 팀원들은 "revert해야 하나 reset해야 하나"로 논쟁 중입니다. 릴리즈 태그도 없어서 "정확히 어느 버전까지 돌아가야 하나"도 불분명합니다.

이 모듈은 그런 상황에서 당황하지 않도록, Git을 형상관리 도구로 제대로 쓰는 방법을 다룹니다. 브랜치 전략, 태그 릴리즈, 안전한 롤백 절차를 실무 중심으로 정리합니다.

이번 챕터에서 배울 것
  • 1GitFlow 브랜치 전략(main/develop/feature/release/hotfix)의 흐름을 설명할 수 있다
  • 2git tag로 릴리즈 기준점을 만들고 배포 이력을 추적할 수 있다
  • 3커밋 메시지에 이슈 번호를 포함해 GitLab에서 이슈-커밋 연결을 활용할 수 있다
  • 4긴급 hotfix 절차(main merge → develop merge)를 순서대로 실행할 수 있다
  • 5잘못된 커밋에 git revert를 안전하게 적용하고 reset과의 차이를 설명할 수 있다

브랜치 전략 — GitFlow

💡개념

GitFlow 브랜치 구조

브랜치 전략은 팀이 코드를 어떻게 나누고 합치는가의 규칙입니다. 규칙이 없으면 누가 어디에 무엇을 push했는지 파악이 어렵고, 긴급 수정이 필요할 때 경로가 없어 혼란이 생깁니다.

GitFlow 브랜치 구조

운영 장애가 났습니다. 누군가 main에 직접 push한 커밋이 테스트 없이 배포됐고, 롤백하려니 "어느 커밋으로 돌아가야 하나"부터 막힙니다. 릴리즈 태그도 없고, 누가 무엇을 바꿨는지 추적할 방법이 없습니다. 브랜치 전략이 없는 팀은 긴급 상황에서 이렇게 무너집니다. 규칙 없이 모두가 한 브랜치에 push하면, 운영 코드와 개발 코드가 뒤섞이고 장애 원인을 찾는 데 배포 복구보다 더 많은 시간이 걸립니다. GitFlow는 소규모~중규모 팀에서 검증된 전략입니다. 브랜치별 역할이 명확하게 분리됩니다.

main ─────────────────────────────────────────── (운영 배포 기준)
  │         ↑ release/1.2 merge           ↑ hotfix/login-bug merge
  │
develop ──────────────────────────────────────── (통합 개발 기준)
  │     ↑ feature/login merge  ↑ feature/dashboard merge
  │
feature/login ─────── (기능 개발)
feature/dashboard ─── (기능 개발)

브랜치 역할 요약:

브랜치역할직접 push 여부
main운영 배포 기준. 항상 배포 가능 상태금지 (MR only)
develop다음 릴리즈 통합 브랜치금지 (MR only)
feature/*기능 단위 개발개인 작업 가능
release/*릴리즈 준비 (QA, 버그픽스)제한적
hotfix/*운영 긴급 수정main에서 분기
로컬 터미널
# feature 브랜치 생성 및 작업
git checkout develop
git pull origin develop
git checkout -b feature/user-logout

# 작업 후 커밋
git add .
git commit -m "feat: 사용자 로그아웃 기능 구현 (#45)"

# develop으로 MR(Merge Request) 요청
git push origin feature/user-logout
# GitLab에서 develop 대상 MR 생성
💡개념

Trunk-Based Development — GitFlow의 대안

팀 규모가 작거나 배포 주기가 짧은 경우, 더 단순한 전략이 유리할 수 있습니다.

비교 항목GitFlowTrunk-Based
브랜치 수많음 (5종)적음 (main + 단기 feature)
릴리즈 주기주/월 단위수시(하루 여러 번 가능)
팀 규모중~대규모소~중규모
적합한 상황명확한 버전 관리 필요CI/CD 자동화가 잘 된 팀

이 모듈에서는 인프라 운영 팀에서 더 자주 보이는 GitFlow를 기준으로 다룹니다.

Git Workflow — 브랜치 전략과 운영 배포 흐름

태그 기반 릴리즈

💡개념

git tag 로 배포 기준점 만들기

배포 기준점이 없으면 "어제 배포본으로 롤백해줘"라는 요청을 받았을 때 정확히 어느 커밋인지 찾기가 어렵습니다. git tag는 특정 커밋에 이름을 붙이는 방법입니다. 한 번 붙이면 브랜치와 달리 이동하지 않습니다.

로컬 터미널
# annotated tag 생성 (메시지 포함, 배포 이력에 남김)
git tag -a v1.2.0 -m "Release v1.2.0 — 로그아웃 기능 추가, 성능 개선"

# 원격 저장소에 push
git push origin v1.2.0

# 전체 태그 목록 확인
git tag -l

# 특정 버전 두 태그 사이의 커밋 목록
git log --oneline v1.1.0..v1.2.0
OUTPUT
a3f9c21 feat: 사용자 로그아웃 기능 구현 (#45)
b82e1d3 fix: 세션 만료 시 리다이렉트 오류 수정 (#43)
c11a027 perf: 쿼리 캐시 레이어 추가 (#40)

배포 이력 추적 루틴:

로컬 터미널
# 가장 최근 태그 확인
git describe --tags --abbrev=0

# 특정 커밋이 어느 태그 기준인지 확인
git describe --tags a3f9c21

# 날짜 기준 배포 이력
git log --oneline --since="2026-01-01" --until="2026-06-01" --decorate | grep "tag:"

실습

1릴리즈 태그 생성 및 푸시

태그 생성은 현재 브랜치의 최신 커밋에 붙습니다. main 브랜치에서 실행해야 운영 기준점으로 사용할 수 있습니다. 먼저 main 브랜치에 있는지 확인합니다.

로컬 터미널
# main 브랜치 확인
git branch --show-current
# 또는
git status | head -1

# main이 아니라면 이동
git checkout main
git pull origin main

# 태그 생성 및 push
git tag -a v1.0.0 -m "Release v1.0.0"
git push origin v1.0.0
git tag -a v1.0.0 -m 'Release v1.0.0' && git push origin v1.0.0
🔍실행 후 확인할 것
  • git tag -l 에 v1.0.0 이 보이는가
  • git show v1.0.0 에서 태그 메시지와 커밋 정보가 함께 출력되는가
  • git push origin v1.0.0 이후 GitLab 저장소 Tags 탭에서 확인 가능한가
  • git log --oneline --decorate | head -5 에서 HEAD -> main, tag: v1.0.0 이 같은 커밋에 표시되는가
2배포 기준 커밋 범위 확인

두 태그 사이의 변경 내역을 확인합니다. 릴리즈 노트 작성이나 롤백 범위 파악에 사용합니다. 이전 태그(v0.9.0)가 없는 경우 첫 커밋부터 확인하려면 git log --oneline v1.0.0을 씁니다.

로컬 터미널
# 이전 릴리즈 이후 커밋 목록
git log --oneline v0.9.0..v1.0.0

# 변경된 파일 목록
git diff --name-only v0.9.0..v1.0.0

# 작성자별 기여 요약
git shortlog v0.9.0..v1.0.0
OUTPUT
a3f9c21 feat: 사용자 로그아웃 기능 구현 (#45)
b82e1d3 fix: 세션 만료 시 리다이렉트 오류 수정 (#43)
c11a027 perf: 쿼리 캐시 레이어 추가 (#40)
git log --oneline v0.9.0..v1.0.0
🔍실행 후 확인할 것
  • 두 태그 사이의 커밋 목록이 예상한 기능/수정 내역과 일치하는가
  • 커밋 메시지에 feat/fix/perf 같은 타입 prefix와 이슈 번호(#N)가 포함돼 있는가
  • git diff --name-only 로 변경 파일 목록이 릴리즈 범위와 일치하는가

이슈-커밋 연결

💡개념

커밋 메시지 컨벤션과 이슈 연결

커밋 메시지를 일관된 형식으로 작성하면, 나중에 "이 변경이 왜 생겼나"를 추적하기 쉬워집니다. GitLab은 커밋 메시지의 #이슈번호를 자동으로 해당 이슈와 연결합니다.

로컬 터미널
# 커밋 메시지 형식 권장
# <type>: <요약> (#이슈번호)
#
# type 종류:
#   feat  — 새 기능
#   fix   — 버그 수정
#   docs  — 문서
#   refac — 리팩터링
#   chore — 빌드/배포/설정 변경

# 예시
git commit -m "fix: 로그인 후 세션 쿠키 누락 수정 (#78)"
git commit -m "feat: Prometheus 메트릭 엔드포인트 추가 (#82)"
git commit -m "chore: application-prod.yml 로그 레벨 WARN으로 변경"
로컬 터미널
# 특정 이슈 번호가 언급된 커밋 찾기
git log --oneline --all | grep "#78"

# 최근 30개 커밋 확인
git log --oneline -30

# 특정 작성자 커밋만 확인
git log --oneline --author="minjun" --since="1 week ago"

# 특정 파일이 언제 마지막으로 변경됐는지
git log --oneline -5 -- src/main/resources/application-prod.yml

트러블슈팅

상황: 장애를 일으키는 커밋이 main에 merge됐고, 빠르게 되돌려야 합니다. git revertgit reset 중 어느 것을 써야 하는지 판단 기준이 핵심입니다.

로컬 터미널
# 문제 커밋 SHA 확인
git log --oneline main | head -10
# 예: d9a3f1c feat: 캐시 로직 변경 (#91) ← 이 커밋이 문제

# 방법 1: git revert (공유 브랜치에서 항상 이 방법 사용)
# 문제 커밋을 취소하는 새 커밋을 만든다 — 이력 보존
git revert d9a3f1c
# 에디터가 열리면 커밋 메시지 확인 후 저장
git push origin main

# 방법 2: git reset --hard (주의: 공유 브랜치에서 사용 금지)
# 이 방법은 혼자 쓰는 feature 브랜치에서만
git reset --hard d9a3f1c~1  # 해당 커밋 이전으로 되돌림
# force push 필요 → 다른 팀원 이력 꼬임 발생 가능

판단 기준:

상황사용할 명령이유
main/develop 등 공유 브랜치git revert이력 보존, force push 불필요
혼자 쓰는 feature 브랜치git reset 가능아직 다른 사람이 pull하지 않음
이미 force push한 상황팀에 알리고 revert이력 복구 시도보다 revert가 안전

원인: feature 브랜치와 develop 브랜치가 동일한 파일의 같은 부분을 각자 수정했습니다. Git이 자동으로 합칠 수 없어 충돌 마커를 삽입하고 멈춥니다.

로컬 터미널
# 충돌 파일 목록 확인
git status | grep "both modified"

# 충돌 마커 확인 (파일 안에 삽입됨)
grep -n "<<<<<<" src/main/resources/application.yml

# 충돌 마커 해석:
# <<<<<<< HEAD          ← 현재 브랜치(develop)의 내용
# spring.datasource.url=jdbc:mysql://develop-db:3306/mydb
# =======
# spring.datasource.url=jdbc:mysql://localhost:3306/mydb_dev
# >>>>>>> feature/new-db-config   ← merge하려는 브랜치 내용

# 직접 편집해서 올바른 내용만 남김 (마커 줄 포함 삭제)
vi src/main/resources/application.yml

# 수정 후 해결 완료 표시
git add src/main/resources/application.yml

# merge 완료
git commit
# (merge 커밋 메시지가 자동으로 채워짐)

# 충돌이 많으면 GUI 도구 활용
git mergetool    # vimdiff, VS Code 등 설정에 따라 실행

충돌 예방 습관:

  • feature 브랜치 작업이 길어지면 주기적으로 git merge develop으로 최신화
  • 설정 파일 같이 충돌 잦은 파일은 MR 전 팀에 알리고 작업
💼
실무 맥락
현업 패턴

실제 업무에서 이 지식이 쓰이는 상황:

인프라/운영 엔지니어에게 형상관리가 실질적으로 필요한 세 장면입니다.

1. 긴급 핫픽스 절차 (운영 버그 발생 시):

로컬 터미널
# main 기반으로 hotfix 브랜치 생성
git checkout main
git pull origin main
git checkout -b hotfix/session-null-pointer

# 수정 후 커밋
git add .
git commit -m "fix: 세션 null 시 NPE 수정 (#101)"

# main에 merge (운영 배포)
git checkout main
git merge hotfix/session-null-pointer
git tag -a v1.2.1 -m "Hotfix v1.2.1 — 세션 NPE 긴급 수정"
git push origin main
git push origin v1.2.1

# develop에도 반영 (재발 방지)
git checkout develop
git merge hotfix/session-null-pointer
git push origin develop

# hotfix 브랜치 삭제
git branch -d hotfix/session-null-pointer
git push origin --delete hotfix/session-null-pointer

2. 배포 이력 추적:

로컬 터미널
# "3주 전 배포본으로 돌아가야 한다" 요청이 오면
git log --oneline --decorate | grep "tag: v"
# 릴리즈 태그가 있어야 정확한 기준점으로 배포 가능

# 특정 날짜 이전 마지막 태그 확인
git log --tags --simplify-by-decoration --pretty="format:%d %ai" | grep "v1\." | head -5

3. 설정 파일 변경 추적: 운영 서버 설정이 언제, 누가, 왜 바뀌었는지 조회합니다.

로컬 터미널
git log --oneline --follow -- config/application-prod.yml
git show <커밋SHA>:config/application-prod.yml

형상관리가 잘 된 팀은 장애 발생 시 "어떤 버전에서 문제가 생겼나"를 5분 안에 파악합니다. 다음 모듈에서는 이 코드를 실제 배포 산출물로 만드는 빌드 도구 실무를 다룹니다.

지식 확인

퀴즈 — 4문제

Q1

Git tag와 branch의 차이로 올바른 것은?

Q2

hotfix 브랜치를 main과 develop 양쪽에 merge하는 이유는?

Q3

git revert와 git reset의 차이에서 운영 환경에서 revert를 선호하는 이유는?

Q4

커밋 메시지에 이슈 번호를 포함하는 이유는?

0 / 4 답변

🧪 실습으로 확인하기

Nginx 설치 및 기동

초급

Linux 서버에 Nginx를 설치하고 systemd 서비스로 등록하여 80포트에서 응답하는 상태까지 만든다.

30📋 3단계💻 직접 환경
실습 시작하기 →

이것도 배워보세요

infra-ops중급 · 60
[Infra Ops] DDL 반영 절차와 Migration 안전 운영
인프라 서비스 운영 트랙 계속
linux입문 · 30
[Linux] 개발자가 왜 리눅스 서버와 커맨드라인을 반드시 배워야 하는가
Linux 트랙 시작점