당신의 코드 리뷰는 아마도 고장 났다
대부분의 코드 리뷰는 원래 찾아야 할 결함의 15~30%를 포착한다. 이는 추측이 아니다. IBM은 1970년대에 이를 측정했고, AT&T, HP, Microsoft의 연구가 수십 년에 걸쳐 동일한 범위를 확인했다.
비공식 리뷰는 저렴하고, 비동기적이며, 사회적으로 받아들여진다. 그러나 버그를 찾는 데는 대부분 비효율적이다. 엔지니어들은 너무 빨리 읽고, 에러 패스를 건너뛰며, 머지를 막는 사람이 되고 싶지 않기 때문에 실제 문제를 지적하는 것을 피한다.
일관되게 60~90%의 결함 제거율을 보고하는 대안이 있다. 이는 1976년 IBM의 Michael Fagan이 발명했다. 도구도 AI도 예산도 필요 없다. 필요한 것은 대부분의 엔지니어링 팀이 주기를 거부하는 것이다. 바로 구조다.
Fagan Inspection이란 무엇인가
Fagan Inspection은 특정 역할, 시간 제한, 진입 기준, 체크리스트를 갖춘 공식적으로 정의된 다단계 검토 프로세스다. 일반적인 풀 리퀘스트 리뷰와 달리, 저자와 리뷰어 간의 대화가 아니다. 진행자, 리더, 검사자, 저자가 참여하는 구조화된 회의다.
저자는 대부분 침묵한다. 회의는 엄격하게 타임박스된다. 그리고 유일한 목표는 결함을 찾는 것이다.
이 프로세스는 여섯 단계를 따른다:
-
Planning(계획). 진행자는 자료를 선택하고, 진입 기준을 검증하고, 역할을 할당하고, 회의를 예약한다. 진입 기준에는 이유가 있다. 초안은 검사하지 않는다. 문서는 완전하고, 컴파일 가능하며, 테스트를 거쳐야 네 명의 시간을 소비할 자격이 있다.
-
Overview(개요). 선택 사항. 검사자가 도메인에 익숙하지 않은 경우 저자가 맥락을 설명한다.
-
Preparation(준비). 각 검사자는 회의 전에 자료를 개별적으로 검토한다. 이는 협상의 여지가 없다. 준비 없이 참석하지 않는다. 검사자는 일반적인 결함 유형에 맞춘 체크리스트를 사용하고 개인적으로 이슈에 주석을 단다.
-
Inspection(검사). 회의 자체. 코드를 작성하지 않은 리더가 한 줄씩 읽어 가며 소리 내어 바꿔 말한다. 검사자는 불일치를 발견하면 이슈를 제기한다. 저자는 듣는다. 아무도 수정안을 제안하지 않는다. 진행자는 시간 제한을 집행하고 회의를 결함 식별에만 집중시킨다.
-
Rework(재작업). 저자가 결함을 수정한다.
-
Follow-up(후속 조치). 진행자가 모든 결함이 처리되었는지 확인한다. 너무 많은 결함이 발견되면 재검사가 수행된다.
네 가지 역할이 프로세스를 정직하게 유지한다. 진행자는 계획하고 통제한다. 저자는 작업을 만들었고 질문을 받을 때만 답한다. 리더는 회의 중에 코드를 바꿔 말하며, 더 느리고 신중한 이해를 강제한다. 검사자, 보통 2~4명이 결함을 찾는다.
비공식 리뷰가 실패하고 Fagan Inspection이 성공하는 이유
차이는 재능이 아니다. 프로세스 설계다.
일반적인 풀 리퀘스트 리뷰에서 리뷰어는 브라우저에서 diff를 읽고, 해피 패스를 훑어보고, 몇 가지 코멘트를 남기고 승인한다. 준비 시간이 없다. 체크리스트가 없다. 리뷰어가 에러 핸들링이나 경계 조건을 검토하도록 강제하는 메커니즘이 없다. 사회적 역학은 철저함이 아니라 속도와 정중함을 보상한다.
Fagan Inspection은 이러한 인센티브를 뒤집는다.
개별 준비는 회의가 시작되기 전에 각 검사자가 실제로 코드를 읽었다는 것을 의미한다. 리더의 바꿔 말하기는 그룹이 코드를 훑어보는 속도가 아니라 이해하는 속도로 처리하도록 강제한다. 체크리스트는 눈에 띄는 것이 아니라 알려진 결함 범주에 주의를 집중시킨다. 시간 압박은 회의가 설계 논쟁으로 빗나가는 것을 방지한다. 그리고 결함 발견과 결함 수정을 분리함으로써 그룹이 누군가 제안한 첫 번째 해결책에 고정되는 것을 막는다.
결과적으로 Fagan Inspection은 테스트나 프로덕션에 도달하기 전에 대부분의 결함을 포착한다.
비용은 인시로 선불된다.
진정한 트레이드오프: 인시 대 결함 유출
대부분의 팀이 Fagan Inspection을 사용하지 않는 이유는 다음과 같다.
한 번의 검사에는 약 250줄의 코드를 검토하기 위해 46명이 최대 2시간 동안 방에 있어야 한다. 이는 작은 변경에 812인시다. 하루에 여러 번 배포하는 현대 CI/CD 워크플로우에서 이는 터무니없어 보인다.
이 프로세스는 관료적으로도 느껴진다. 진입 기준, 공식적인 역할, 인쇄된 체크리스트, 후속 검증. 대부분의 엔지니어는 원칙적으로 이를 싫어할 것이다. 그리고 큰 diff에는 확장되지 않는다. 2,000줄의 리팩터링에는 여덟 번의 별도 검사 회의가 필요할 것이다.
하지만 회의 비용이 아닌 총비용을 보면 계산이 달라진다.
IBM의 원본 데이터는 검사 중에 결함을 찾아 수정하는 비용이 테스트 중에 동일한 결함을 찾아 수정하는 비용의 약 10분의 1이었음을 보여주었다. 프로덕션에 유출되면 비율은 20~30배까지 커졌다.
그렇다, 검사는 비싸다. 그럼에도 프로덕션 인시던트를 디버깅하고, 리액티브 수정으로 스프린트 용량을 태우고, 고객 신뢰를 잃는 것보다는 저렴하다.
문제는 절약이 보이지 않는다는 것이다. 방지한 버그는 측정할 수 없다. 회의 비용은 즉각적이고 명백하다. 그것이 대부분의 조직에서 비공식 리뷰가 이기는 이유다. 보이지 않는 품질보다 보이는 속도를 최적화한다.
2026년에 경량 Fagan Inspection 실행하기
전체 의식을 채택할 필요는 없다. 대부분의 팀은 핵심 메커니즘을 유지하고 서류 작업을 버림으로써 오버헤드의 20%로 70%의 이점을 얻을 수 있다.
실용적인 순서는 다음과 같다:
모든 동기식 리뷰 전에 개별 준비를 필수로 한다. 코드를 읽지 않았다면 참석하지 않는다.
코드를 작성하지 않은 리더를 배정하여 논리를 소리 내어 설명하게 한다. 저자가 주도하지 않게 한다. 바꿔 말하기는 그룹이 모든 분기를 처리하도록 강제한다.
팀에서 가장 흔한 결함 유형에 맞춘 체크리스트를 사용한다. 아래 목록으로 시작하고 유출된 결함에서 배우면서 항목을 추가한다.
90분으로 타임박스한다. 끝나지 않았더라도 정시에 종료한다. 피로가 품질을 해치게 하지 말고 두 번째 세션을 예약한다.
저자를 수동적으로 유지한다. 그들은 명확화 질문에만 답한다. 설계 선택을 방어하지 않는다.
해결책이 아닌 결함을 기록한다. 회의 후에 결함을 수정한다.
이를 구체화하기 위해, 검사를 계획하고 시간을 추정하며 역할별 체크리스트를 출력하는 작은 Python 스크립트가 있다:
#!/usr/bin/env python3
"""
Plan a Fagan-style inspection: estimate time and emit checklists.
"""
import argparse
def count_lines(filepath):
"""Count non-blank lines."""
try:
with open(filepath, "r") as f:
return sum(1 for line in f if line.strip())
except Exception:
return 0
def plan_inspection(files, rate=125):
"""
rate: reviewable lines per hour. Fagan recommended 100-125 for code.
"""
total = sum(count_lines(f) for f in files)
hours = total / rate
minutes = hours * 60
print(f"Total reviewable lines: {total}")
print(f"At {rate} lines/hour, schedule: {hours:.1f} hours ({minutes:.0f} min)")
if hours > 2:
sessions = int(hours / 2) + 1
print(f"WARNING: exceeds 2-hour limit. Split into {sessions} sessions.")
print("\n--- ROLE: Reader ---")
print("Paraphrase each block aloud. Do not just read variable names.")
print("Pause at every conditional, loop boundary, and API call.")
print("\n--- ROLE: Inspector ---")
checklist = [
"Off-by-one in loops and array or slice access",
"Null, None, or undefined dereferences",
"Resource leaks: files, connections, locks, contexts",
"Error paths: are they handled, returned, and tested?",
"Return values: are they checked before use?",
"Shared mutable state and thread safety",
"Boundary conditions and input validation",
"Invariant violations: what should stay true, and does it?",
]
for item in checklist:
print(f" [ ] {item}")
print("\n--- ROLE: Moderator ---")
print("Start on time. End on time.")
print("No design debates. No solution proposals.")
print("Record each defect with: file, line, severity, type.")
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Plan a Fagan inspection")
parser.add_argument("files", nargs="+", help="Source files to inspect")
parser.add_argument("--rate", type=int, default=125, help="Lines per hour")
args = parser.parse_args()
plan_inspection(args.files, args.rate)
이를 inspect.py로 저장하고 python inspect.py src/auth.py src/orders.py를 실행하면 시간 추정과 체크리스트를 얻을 수 있다.
자주 묻는 질문
Fagan Inspection이란 무엇인가?
Fagan Inspection은 정의된 역할, 진입 기준, 체크리스트를 갖춘 구조화된 6단계 검토 프로세스다. 1976년 IBM의 Michael Fagan이 개발하여 테스트 전에 소프트웨어 작업 산출물의 결함을 찾기 위해 만들어졌다.
Fagan Inspection과 풀 리퀘스트 리뷰의 차이점은 무엇인가?
풀 리퀘스트 리뷰는 일반적으로 비동기적이고, 비공식적이며, 저자 주도적이다. Fagan Inspection은 할당된 역할, 필수 개별 준비, 엄격한 시간 제한, 그리고 다른 사람이 결함을 찾는 동안 저자가 침묵을 지키는 규칙을 가진 동기식 회의다.
왜 Fagan Inspection이 더 널리 퍼지지 않았는가?
인시 비용이 많이 들고, 현대 팀에게 관료적으로 느껴지며, 크고 빈번한 변경에 잘 확장되지 않는다. 비용은 가시적이고 즉각적이다. 방지된 결함은 보이지 않는다.
Fagan Inspection은 애자일이나 CI/CD 환경에서 작동할 수 있는가?
예, 하지만 수정이 필요하다. 대부분의 팀은 경량 버전을 사용한다: 필수 개별 준비, 바꿔 말하는 리더, 체크리스트, 엄격한 타임박스. 전체 공식 프로세스는 일반적으로 중요하거나 고위험 모듈용으로 예약된다.
한 모듈에서 시도해 보기
프로세스를 다시 작성할 필요는 없다. 지난 달에 유출 결함이 있던 모듈 하나를 고른다. 이를 작성하지 않은 세 명의 엔지니어를 모은다. 24시간 전에 코드와 체크리스트를 준다. 90분을 예약한다. 리더를 배정한다. 저자가 듣게 한다.
무엇을 찾았는지 측정한다. 그런 다음 회의 비용이 버그 비용보다 더 많이 들었는지 결정한다.
원본 데이터가 필요하다면, Fagan의 1976년 논문 “Design and Code Inspections to Reduce Errors in Program Development”가 여전히 최고의 참고 자료다. 50년이 지났지만 대부분의 팀은 아직 따라잡지 못했다.