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. 동작 원리
리뷰는 대체로 다음 순서로 흐른다.
- 작업 브랜치를 만들어 커밋한다.
- 원격 저장소로 푸시(push)한다.
- 대상 브랜치(예:
main)를 향해 PR을 연다. - 자동 검사(CI: 빌드, 테스트, 린트)가 실행된다.
- 리뷰어가 diff를 읽고 줄 단위로 코멘트를 남긴다.
- 작성자가 수정 커밋을 추가로 푸시한다. PR은 자동으로 갱신된다.
- 승인 조건(필수 승인 수, CI 통과)이 충족되면 병합한다.
팀은 브랜치 보호 규칙(branch protection rule)으로 이 흐름을 강제할 수 있다. 예를 들어 main에 직접 푸시를 막고, 최소 1명의 승인과 CI 통과를 병합 조건으로 건다.
병합 방식은 세 가지가 흔하다.
| 방식 | 결과 |
|---|---|
| Merge commit | 병합 커밋이 생기고 브랜치 이력이 그대로 보존된다 |
| Squash and merge | PR의 모든 커밋이 하나로 합쳐져 반영된다 |
| Rebase and merge | 커밋들이 대상 브랜치 위에 선형으로 재배치된다 |
4. 코드 예제
PR을 열기까지의 기본 명령어다.
# 최신 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리뷰 코멘트를 반영할 때는 같은 브랜치에 커밋을 추가로 푸시하면 된다.
git add src/order.ts
git commit -m "refactor: 리뷰 반영 - 반올림 로직을 함수로 분리"
git push리뷰 대상이 되는 변경의 예시다. 리뷰어는 경계값과 테스트 누락을 확인한다.
// 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)); // 05. 시간 복잡도 또는 성능 특성
알고리즘 복잡도 대신 프로세스 관점의 특성을 본다.
- 리뷰 비용은 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이 리뷰 품질과 속도를 높인다.
- 좋은 코멘트는 구체적이고 근거와 대안을 포함하며, 사람이 아닌 코드를 대상으로 한다.