페어 프로그래밍과 코드 리뷰 — 협업으로 코드 품질 높이기
혼자 짠 코드에 "왜 이렇게 짰지?" 싶은 순간, 옆에 누가 있었으면 좋겠다고 생각한 적 있으신가요?
페어 프로그래밍과 코드 리뷰는 모두 "여러 사람의 눈"으로 코드 품질을 높이는 방법입니다. 비슷해 보이지만 타이밍과 방식이 다릅니다. 각각 어떤 상황에 효과적인지 정리해보겠습니다.
이게 뭔가요?
페어 프로그래밍
두 사람이 하나의 컴퓨터에서 함께 코드를 작성하는 방식입니다.
- 드라이버(Driver): 키보드를 잡고 코드를 직접 타이핑
- 네비게이터(Navigator): 코드를 관찰하며 방향을 제시, 버그를 잡고, 큰 그림을 생각
일정 시간마다(보통 15~30분) 역할을 교대합니다.
코드 리뷰
코드가 작성된 후, 다른 개발자가 변경 사항을 검토하고 피드백을 주는 과정입니다.
- 보통 Pull Request(PR) 기반
- 비동기적으로 진행 (리뷰어가 시간 날 때 확인)
- 승인(Approve) 후 머지
왜 필요한가요?
버그를 일찍 잡을수록 비용이 적습니다
버그 수정 비용 (상대적):
코딩 중 발견: 1x
코드 리뷰에서 발견: 5x
테스트에서 발견: 10x
프로덕션에서 발견: 100x
페어 프로그래밍은 코딩 중에, 코드 리뷰는 머지 전에 버그를 잡습니다. 둘 다 프로덕션에 도달하기 전에 문제를 걸러내는 장치입니다.
지식 공유
한 사람만 아는 코드(Bus Factor = 1)는 그 사람이 휴가를 가거나 퇴사하면 위험합니다.
- 페어 프로그래밍: 작성 과정에서 자연스럽게 지식이 전달
- 코드 리뷰: 다른 사람의 코드를 읽으면서 시스템을 이해
어떻게 동작하나요?
페어 프로그래밍 방식
1. Driver-Navigator (가장 일반적)
[드라이버] [네비게이터]
코드를 타이핑 전체 구조를 생각
세부 구현에 집중 "이 메서드 너무 길어지는데
문법, 변수명 처리 분리하면 어떨까?"
"여기 null 체크 빠진 것 같아"
↕ 15~30분마다 역할 교대
2. Ping-Pong (TDD와 결합)
A: 실패하는 테스트 작성 (Red)
B: 테스트를 통과하는 최소 코드 작성 (Green)
B: 실패하는 테스트 작성 (Red)
A: 테스트를 통과하는 최소 코드 작성 (Green)
... 반복
3. Strong-Style
규칙: "아이디어가 있으면 반드시 상대방의 손을 거쳐야 한다"
→ 네비게이터가 생각을 말하면, 드라이버가 코드로 구현
→ 네비게이터의 의도를 드라이버가 이해해야 하므로
커뮤니케이션이 강제됨
효과적인 페어 프로그래밍을 위한 팁:
- 시작 전에 목표를 합의 ("이번 세션에서 주문 API 리팩토링을 끝내자")
- 25분 코딩 + 5분 휴식 (포모도로 기법 적용)
- 실력 차이가 클 때는 경험자가 네비게이터를 맡는 것이 효과적
- 원격이면 VS Code Live Share, JetBrains Code With Me 같은 도구 활용
코드 리뷰 프로세스
[코드 작성] → [PR 생성] → [리뷰어 배정] → [피드백] → [수정] → [승인] → [머지]
좋은 PR의 조건:
## PR 제목
feat: 주문 취소 시 재고 자동 복원
## 변경 사항
- 주문 취소 이벤트 리스너 추가
- 재고 복원 로직 구현
- 취소 실패 시 보상 트랜잭션 처리
## 테스트
- 정상 취소 시 재고 복원 확인
- 이미 취소된 주문 재취소 시 예외 처리
- 재고 복원 실패 시 알림 발송 확인
## 리뷰 포인트
- `InventoryService.restore()` 메서드의 동시성 처리가
적절한지 확인 부탁드립니다
- PR 크기: 400줄 이하 권장 (Google 기준). 커지면 리뷰 품질이 급격히 떨어짐
- 하나의 PR은 하나의 목적 (기능 추가와 리팩토링을 섞지 않기)
- 컨텍스트 제공: 왜 이렇게 바꿨는지 설명
리뷰어 체크리스트:
□ 코드가 의도한 대로 동작하는가?
□ 엣지 케이스가 처리되어 있는가?
□ 코드가 읽기 쉬운가? (변수명, 메서드명, 구조)
□ 테스트가 적절한가?
□ 보안 이슈는 없는가? (SQL Injection, XSS 등)
□ 성능 이슈는 없는가? (N+1 쿼리, 불필요한 루프 등)
□ 기존 코드와 일관성이 있는가?
좋은 피드백 vs 나쁜 피드백:
❌ "이 코드 별로예요"
✅ "이 부분에서 N+1 쿼리가 발생할 수 있어요.
fetch join을 사용하면 어떨까요?"
❌ "왜 이렇게 짰어요?"
✅ "이 방식도 동작하지만, Optional.map()을 쓰면
null 체크 없이 더 간결하게 표현할 수 있어요.
예시: user.map(User::getName).orElse("익명")"
❌ "변수명 바꾸세요" (20개 동시에)
✅ "전반적으로 변수명이 축약되어 있는데, 팀 컨벤션인
풀네임 방식으로 통일하면 좋겠어요. 예를 들어
usr → user, amt → amount처럼요"
피드백 분류:
[필수] 머지 전에 반드시 수정해야 하는 사항
→ 버그, 보안 이슈, 데이터 유실 가능성
[제안] 수정하면 좋지만 현재 PR에서 꼭 안 해도 되는 사항
→ 리팩토링, 네이밍 개선, 패턴 적용
[칭찬] 잘한 부분도 언급
→ "이 부분 깔끔하게 처리하셨네요!" (동기 부여)
[질문] 이해가 안 되는 부분
→ "이 로직의 의도가 뭔지 설명해주실 수 있나요?"
자주 헷갈리는 포인트
페어 프로그래밍은 비효율적이지 않나요?
두 사람이 하나의 코드를 짜니까 "생산성이 절반"이라고 생각하기 쉽습니다. 하지만 연구 결과는 다릅니다:
- 코드 작성 시간은 약 15% 증가
- 하지만 버그 수가 15~60% 감소하고, 후속 디버깅 시간이 크게 줄어듦
- 전체 사이클(개발 + 디버깅 + 코드 리뷰)로 보면 비슷하거나 더 빠름
모든 코드를 페어로 짤 필요는 없습니다. 이런 경우에 특히 효과적입니다:
- 복잡한 비즈니스 로직
- 새로운 아키텍처 결정이 필요한 코드
- 신입 개발자 온보딩
- 원인을 모르는 버그 디버깅
코드 리뷰에 시간을 얼마나 써야 하나요?
Google의 권장:
- 리뷰 요청 후 24시간 이내 첫 피드백
- 한 번에 집중 리뷰하는 시간은 60분 이내 (이후 집중력 저하)
- 한 주에 개발 시간의 약 20~25% 를 리뷰에 할당
둘 다 해야 하나요?
둘은 보완적입니다:
| 측면 | 페어 프로그래밍 | 코드 리뷰 |
|---|---|---|
| 타이밍 | 코딩 중 (동기적) | 코딩 후 (비동기적) |
| 피드백 속도 | 즉각적 | 수 시간~수 일 |
| 설계 영향력 | 설계 단계에서 개입 | 이미 완성된 코드에 피드백 |
| 지식 전달 | 깊고 밀도 높음 | 넓고 얕음 |
| 비용 | 동시에 2명 투입 | 비동기, 각자 시간 분배 |
- 복잡한 작업 → 페어 프로그래밍이 효과적
- 일상적인 작업 → 코드 리뷰만으로 충분
- 두 가지를 상황에 맞게 조합하는 게 이상적
리뷰 코멘트가 너무 많으면 어떡하나요?
- PR이 크면 코멘트도 많아짐 → PR을 작게 나누는 게 근본 해결
- 스타일 관련 코멘트가 많으면 → Linter/Formatter로 자동화
- 같은 패턴의 코멘트가 반복되면 → 팀 컨벤션 문서로 정리
정리
- 페어 프로그래밍은 코딩 중에 실시간으로 코드 품질을 높이는 동기적 협업 방식
- 코드 리뷰는 완성된 코드를 검토하는 비동기적 품질 관리 장치
- 좋은 PR은 작고(400줄 이하), 목적이 명확하며, 변경 이유를 설명함
- 피드백은 "무엇이 문제인지"와 "어떻게 개선할 수 있는지"를 함께 제시
- 페어 프로그래밍은 복잡한 작업에, 코드 리뷰는 일상적 작업에 효과적 — 상황에 맞게 조합