본문 바로가기
TYLER SONGBlog
← Blog index
CS학습5 min read

Code Review: 병합 전에 동료의 눈으로 변경 사항을 검증하는 협업 절차

코드 리뷰(Code Review)는 작성자가 아닌 다른 개발자가 변경 사항을 읽고 결함, 설계, 가독성을 검토한 뒤 병합(merge)을 승인하는 절차다. Git 기반 협업에서는 풀 리퀘스트(Pull Request, PR)나 머지 리퀘스트(Merge Request, MR)로 진행한다. 이 글은 리뷰의 흐름, 브랜치 보호 규칙, 좋은 PR과 리뷰 코멘트 작성법

By 송민성

1. 개념

코드 리뷰(Code Review)는 작성자가 아닌 다른 개발자가 코드 변경 사항(diff)을 읽고 검토한 뒤 의견을 남기거나 승인하는 활동이다. 검토 대상은 버그뿐 아니라 설계, 가독성, 테스트, 보안, 팀 컨벤션까지 포함한다.

Git 호스팅 서비스(GitHub, GitLab 등)에서는 보통 다음 단위로 진행한다.

  • 풀 리퀘스트(Pull Request, PR): GitHub의 용어. 내 브랜치의 변경을 대상 브랜치에 병합해 달라는 요청이다.
  • 머지 리퀘스트(Merge Request, MR): GitLab의 같은 개념이다.
  • 리뷰어(Reviewer): 변경을 검토하는 사람.
  • 승인(Approve) / 변경 요청(Request changes) / 코멘트(Comment): 리뷰 결과의 세 가지 기본 상태.

2. 왜 사용하는가

  • 결함 조기 발견: 작성자는 자기 코드의 가정을 놓치기 쉽다. 다른 사람은 그 가정을 새로 검증한다.
  • 지식 공유: 코드베이스의 변경 맥락이 팀에 퍼져 특정 인물에 대한 의존(버스 팩터, bus factor)이 줄어든다.
  • 일관성 유지: 네이밍, 구조, 에러 처리 방식이 팀 기준에 맞게 유지된다.
  • 변경 이력의 품질: PR 설명과 리뷰 대화가 "왜 이렇게 바꿨는가"의 기록으로 남는다.

3. 동작 원리

리뷰는 대체로 다음 순서로 흐른다.

  1. 작업 브랜치를 만들어 커밋한다.
  2. 원격 저장소로 푸시(push)한다.
  3. 대상 브랜치(예: main)를 향해 PR을 연다.
  4. 자동 검사(CI: 빌드, 테스트, 린트)가 실행된다.
  5. 리뷰어가 diff를 읽고 줄 단위로 코멘트를 남긴다.
  6. 작성자가 수정 커밋을 추가로 푸시한다. PR은 자동으로 갱신된다.
  7. 승인 조건(필수 승인 수, CI 통과)이 충족되면 병합한다.

팀은 브랜치 보호 규칙(branch protection rule)으로 이 흐름을 강제할 수 있다. 예를 들어 main에 직접 푸시를 막고, 최소 1명의 승인과 CI 통과를 병합 조건으로 건다.

병합 방식은 세 가지가 흔하다.

방식결과
Merge commit병합 커밋이 생기고 브랜치 이력이 그대로 보존된다
Squash and mergePR의 모든 커밋이 하나로 합쳐져 반영된다
Rebase and merge커밋들이 대상 브랜치 위에 선형으로 재배치된다

4. 코드 예제

PR을 열기까지의 기본 명령어다.

shell
# 최신 main 기준으로 작업 브랜치 생성 git switch main git pull origin main git switch -c feature/order-total-fix # 변경 후 커밋 git add src/order.ts git commit -m "fix: 할인율 적용 시 합계 반올림 오류 수정" # 원격에 푸시 (이후 호스팅 서비스에서 PR 생성) git push -u origin feature/order-total-fix

리뷰 코멘트를 반영할 때는 같은 브랜치에 커밋을 추가로 푸시하면 된다.

shell
git add src/order.ts git commit -m "refactor: 리뷰 반영 - 반올림 로직을 함수로 분리" git push

리뷰 대상이 되는 변경의 예시다. 리뷰어는 경계값과 테스트 누락을 확인한다.

typescript
// src/order.ts export function calcTotal(price: number, qty: number, discountRate: number): number { if (discountRate < 0 || discountRate > 1) { throw new RangeError("discountRate는 0 이상 1 이하여야 합니다."); } const raw = price * qty * (1 - discountRate); return Math.round(raw); } // 리뷰어가 확인할 만한 경계값 검증 console.log(calcTotal(1000, 3, 0)); // 3000 console.log(calcTotal(1000, 3, 0.1)); // 2700 console.log(calcTotal(1000, 3, 1)); // 0

5. 시간 복잡도 또는 성능 특성

알고리즘 복잡도 대신 프로세스 관점의 특성을 본다.

  • 리뷰 비용은 diff 크기에 따라 커진다. 변경이 클수록 리뷰어가 놓치는 부분이 늘어나는 경향이 있어, 변경을 작게 나누는 것이 일반적인 권장 사항이다.
  • 리뷰 대기 시간은 병목이 된다. 팀 단위로 응답 목표 시간(예: 영업일 기준 하루 이내)을 정해 두면 흐름이 끊기지 않는다.
  • 자동화 가능한 항목(포맷, 린트, 타입 검사)은 CI에 맡기면 사람의 리뷰 시간을 설계와 로직 검토에 쓸 수 있다.

6. 실무 사용 사례

  • 작성자 쪽 체크리스트

- PR 제목과 설명에 변경 이유, 영향 범위, 테스트 방법을 적는다. - 하나의 PR에는 하나의 목적만 담는다. - 제출 전에 직접 diff를 한 번 읽어 본다.

  • 리뷰어 쪽 확인 항목

- 요구사항을 정확히 만족하는가 - 예외 상황과 경계값을 처리하는가 - 테스트가 변경을 충분히 검증하는가 - 이름과 구조가 읽기 쉬운가 - 보안상 민감한 정보(키, 토큰)가 포함되지 않았는가

  • 코멘트 작성 예

- 나쁜 예: "이거 이상한데요." - 좋은 예: "discountRate가 1을 넘으면 음수 금액이 나올 수 있어 보입니다. 입력 검증을 추가하면 어떨까요?"

  • CODEOWNERS 파일로 경로별 담당 리뷰어를 자동 지정하는 방식도 널리 쓰인다.

7. 주의할 점

  • 사람이 아니라 코드를 평가한다. 코멘트는 근거와 제안을 함께 적는다.
  • 필수 수정과 취향 차이를 구분한다. 필수가 아닌 제안은 "nit:" 같은 접두어로 표시하는 관례가 있다.
  • 거대한 PR은 피한다. 리팩터링과 기능 추가를 한 PR에 섞으면 검토가 어렵다.
  • 승인만 누르는 형식적 리뷰(rubber stamping)를 경계한다.
  • 리뷰 중 이미 푸시한 커밋의 이력을 강제 푸시(git push --force)로 바꾸면 리뷰어가 이전 코멘트의 맥락을 잃을 수 있다. 팀 규칙에 따라 신중히 사용한다.
  • 논쟁이 길어지면 코멘트 대신 짧은 대화로 풀고, 결론은 PR에 기록한다.

8. 핵심 정리

  • 코드 리뷰는 병합 전에 다른 개발자가 변경 사항을 검증하는 절차이며, Git 협업에서는 PR/MR로 수행한다.
  • 흐름은 브랜치 작성 → 푸시 → PR → CI와 리뷰 → 수정 → 승인 → 병합이다.
  • 브랜치 보호 규칙으로 승인과 CI 통과를 병합 조건으로 강제할 수 있다.
  • 작고 목적이 분명한 PR이 리뷰 품질과 속도를 높인다.
  • 좋은 코멘트는 구체적이고 근거와 대안을 포함하며, 사람이 아닌 코드를 대상으로 한다.