본문으로 건너뛰기
입문20

Git과 버전 관리: 브랜치, 커밋, PR의 기본 구조

개발자가 "이 브랜치에 배포했어요", "PR 올렸어요"라고 할 때 무슨 뜻인지 이해하려면 Git의 기본 개념부터 알아야 한다.

  • #Git
  • #버전관리
  • #브랜치
  • #PR

개념

버전 관리가 필요한 이유

여러 사람이 같은 코드를 동시에 수정하면, 누가 뭘 언제 바꿨는지 추적할 방법이 필요하다. Git은 코드의 변경 이력을 기록하고, 여러 사람의 작업을 안전하게 합치는 도구다.

커밋(Commit) — 변경의 스냅샷

코드를 수정하고 "여기까지 저장"하는 단위를 커밋이라 한다. 각 커밋에는 무엇을 왜 바꿨는지 설명하는 메시지가 붙는다.

커밋 A: "장바구니 담기 버튼 추가"
커밋 B: "할인 계산 로직 수정"
커밋 C: "테스트 케이스 추가"

이 커밋들이 시간 순서대로 쌓이면서 코드의 전체 역사가 만들어진다.

브랜치(Branch) — 독립된 작업 공간

브랜치는 원본 코드(보통 main이라 부르는 브랜치)에서 갈라져 나온 독립된 작업 공간이다. 새 기능을 개발할 때 main을 직접 건드리지 않고 별도 브랜치에서 작업하면, 그 기능이 완성되기 전까지 다른 사람들은 영향을 받지 않는다.

main ──●──●──●───────────●──  (계속 안정적으로 운영되는 코드)
        \                 /
         ●──●──●──●──────    feature/coupon-discount (새 기능 작업 브랜치)

PR(Pull Request) — 병합 전 검토 요청

기능 브랜치에서 작업이 끝나면, 이 변경을 main에 합쳐달라고 요청하는 것이 PR이다. PR은 단순히 코드를 합치는 절차가 아니라, 다른 팀원이 변경 내용을 검토(리뷰)할 기회이기도 하다 — QA가 PR 단계에서 diff를 확인하는 것도 이 검토 과정의 일부다(레슨 8에서 자세히 다룬다).

Diff — 무엇이 바뀌었는지 보여주는 화면

Diff는 변경 전후 코드를 나란히(또는 +/- 표시로) 비교해서 보여준다.

  function calculateTotal(cartItems, couponRate) {
    let total = 0
    for (let item of cartItems) {
      total = total + item.price
    }
-   if (couponRate > 0) {
+   if (couponRate > 0 && couponRate <= 1) {
      total = applyDiscount(total, couponRate)
    }
    return total
  }

-로 시작하는 줄은 삭제된 코드, +로 시작하는 줄은 추가된 코드다. 이 예시는 "쿠폰 비율이 0보다 크기만 하면"이었던 조건을 "0보다 크고 1 이하일 때만"으로 좁힌 변경이다 — 레슨 1에서 배운 조건문 읽기 능력이 여기서 그대로 쓰인다.

머지(Merge)와 충돌(Conflict)

PR이 승인되면 기능 브랜치가 main에 합쳐진다(머지). 만약 같은 코드 부분을 여러 사람이 동시에 다르게 고쳤다면 충돌이 발생하고, 사람이 직접 어느 쪽을 남길지 결정해야 한다.

실무에서 왜 필요한가

"이번 스프린트에 뭐가 바뀌었는지" 파악하려면 커밋 이력과 PR 목록을 볼 줄 알아야 한다. 또한 "이 버그가 언제부터 생겼는지" 추적할 때, 여러 커밋을 거슬러 올라가며 "어느 커밋부터 이 문제가 생겼는지" 찾는 작업(실무에서는 이진 탐색으로 범위를 좁히기도 한다)도 Git 기본기 없이는 불가능하다. 레슨 8에서 다룰 "PR diff에서 리스크 읽기"의 전제 지식이 바로 이 레슨이다.

실습 과제

과제 1 — 커밋 메시지로 변경 추측하기 (10분)

다음 커밋 메시지 목록을 보고, 이번 스프린트에 어떤 영역에 변경이 집중됐는지, QA로서 어디를 중점적으로 재확인해야 할지 추측한다.

"결제 API 응답 타임아웃 처리 추가"
"결제 실패 시 재시도 로직 수정"
"주문 상세 페이지 UI 리팩터링"
"결제 확인 이메일 템플릿 문구 수정"

과제 2 — Diff 읽기 연습 (10분)

이 레슨의 diff 예시(couponRate <= 1 조건 추가)를 보고, 이 변경으로 인해 이전에 통과하던 어떤 테스트 케이스가 여전히 유효한지, 새로 추가해야 할 테스트 케이스는 무엇일지(예: couponRate = 1.5 같은 값) 적어본다.

자가 체크리스트

  • 커밋·브랜치·PR·머지의 관계를 설명할 수 있다
  • Diff에서 +/- 표시가 무엇을 뜻하는지 설명할 수 있다
  • 브랜치가 왜 여러 사람의 동시 작업을 안전하게 만드는지 설명할 수 있다
  • 충돌이 언제, 왜 발생하는지 설명할 수 있다

흔한 실수

  • PR과 머지를 같은 것으로 착각한다. PR은 "병합해달라는 요청 + 검토 과정"이고, 머지는 그 요청이 승인되어 실제로 합쳐지는 동작이다.
  • Diff에서 +/- 줄만 보고 주변 맥락(바뀌지 않은 코드)은 무시한다. 변경이 기존 로직과 어떻게 상호작용하는지 보려면 주변 코드도 함께 읽어야 한다.
  • 커밋 이력을 전혀 들여다보지 않고 "그냥 최신 버전만" 테스트한다. 무엇이, 언제 바뀌었는지 알아야 회귀 테스트 범위를 정확히 좁힐 수 있다.

참고 자료