소프트웨어 공학 100 주제 시리즈의 82번째 글이다. (카테고리: 품질·신뢰성·보안)

한 줄 요약

Fagan 인스펙션은 역할·입출 조건·체크리스트·결함 기록을 갖춘 정형 검토 프로세스로, 결함을 찾는 일과 그 데이터로 개발 과정을 개선하는 일을 한 묶음으로 설계했다. 오늘날의 PR 리뷰는 그 경량화된 후손이며, 둘의 차이를 알면 언제 무엇을 써야 하는지 판단할 수 있다.

왜 필요한가

PR 리뷰는 대부분 “한 명이 diff 를 훑고 승인” 으로 끝난다. 일상 변경에는 충분하다. 그러나 다음 같은 산출물에서는 이 방식이 자주 실패한다.

  • 결제 정산 로직, 권한 모델, 암호 프로토콜 구현처럼 한 번의 결함이 비싼 코드
  • 수천 줄의 데이터 마이그레이션 스크립트처럼 diff 로 보면 맥락이 안 보이는 산출물
  • 설계 문서·인터페이스 명세처럼 실행해서 확인할 수 없는 산출물

이런 곳에서 “LGTM” 은 리뷰어가 무엇을 확인했는지, 무엇을 확인하지 않았는지 아무 기록도 남기지 않는다. 정형 검토는 검토 행위 자체를 정의된 절차와 측정 가능한 산출물로 바꾼다.

핵심 개념

원전: Fagan, 1976

IBM 의 Michael Fagan 은 Design and code inspections to reduce errors in program development (IBM Systems Journal 15(3), 1976, pp.182–211)에서 설계와 코드에 대한 정형 인스펙션을 제안했다. 10년 뒤 Advances in software inspections (IEEE TSE SE-12(7), 1986, pp.744–751)에서 경험을 보강했다. 핵심 발상은 둘이다.

  1. 실행 가능한 코드가 나올 때까지 검증을 미루지 말고, 개발 단계의 주요 산출물마다 검사 지점을 둔다.
  2. 검사에서 나온 결함을 분류하고 기록해서, 어떤 종류의 결함이 어디서 생기는지를 개발 과정 개선에 되먹인다.

두 번째가 흔히 잊힌다. Fagan 인스펙션은 “꼼꼼한 리뷰” 가 아니라 측정되는 프로세스다.

단계

 계획 ─▶ 개요 ─▶ 준비 ─▶ 인스펙션 회의 ─▶ 재작업 ─▶ 후속 조치
 (Planning) (Overview) (Preparation) (Inspection) (Rework) (Follow-up)
   │                                                   │
   └──── 입구 조건(entry criteria) ········ 출구 조건(exit criteria) ┘
단계 하는 일 산출물
계획 모더레이터가 입구 조건(예: 컴파일됨, 명세 확정)을 확인하고 팀·일정·자료를 정한다 인스펙션 일정, 자료 묶음
개요 작성자가 전체 맥락과 설계 의도를 짧게 설명한다(필요할 때) 공유된 맥락
준비 각 검사자가 혼자 자료를 읽고 체크리스트로 의심 지점을 표시한다 개인 메모
인스펙션 회의 낭독자(reader)가 산출물을 자기 말로 풀어 읽고, 모두가 결함을 제기한다. 기록자가 결함을 분류해 남긴다. 해결책 토론은 하지 않는다 결함 목록(위치, 유형, 심각도)
재작업 작성자가 결함을 고친다 수정본
후속 조치 모더레이터가 모든 결함이 처리됐는지 확인하고, 출구 조건과 재인스펙션 여부를 판단한다 종료 판정, 결함 데이터

1976년 논문은 개요·준비·인스펙션·재작업·후속의 다섯 단계를 중심으로 설명하고, 계획은 이후 실무와 표준에서 독립 단계로 명시된다.

역할

역할 책임 포인트
모더레이터 진행, 입출 조건 판정, 데이터 관리 작성자가 아니어야 하고 훈련받은 사람
작성자 자료 제공, 질문 응답, 재작업 낭독자를 겸하지 않는다
낭독자 산출물을 자기 말로 풀어 설명 작성자의 의도가 아닌 쓰인 그대로를 드러낸다
검사자 결함 제기 테스터 같은 다른 관점을 일부러 섞는다
기록자 결함 분류·기록 모더레이터가 겸하기도 한다

낭독자를 작성자와 분리하는 이유가 중요하다. 작성자가 읽으면 머릿속 의도대로 읽어 버린다. 다른 사람이 풀어 읽다가 막히는 곳이 대개 결함이거나 결함의 원인인 모호함이다.

IEEE 1028 의 다섯 가지 검토

IEEE 1028-2008 (Standard for Software Reviews and Audits) 은 검토를 다섯 유형으로 나누고 유형별 수행 절차를 정한다. 이 표준은 2019년 Inactive-Reserved 상태가 되었지만, 검토 유형을 구분하는 기준 문헌으로 여전히 쓸모 있다. 표의 목적·결정권 열은 필자가 요약한 것이다.

유형 목적 정형성 결정권
관리 검토 (management review) 진척·계획·자원 판단 중간 관리자
기술 검토 (technical review) 산출물의 기술적 적합성 평가, 대안 검토 중간 검토 팀 권고
인스펙션 (inspection) 결함 검출, 데이터 수집 가장 높음 출구 조건 기준
워크스루 (walk-through) 작성자 주도로 설명하며 결함·대안 탐색, 학습 낮음 작성자
감사 (audit) 표준·계약·절차 준수의 독립적 평가 높음 외부·독립

인스펙션만이 “해결책 토론 금지” 를 규칙으로 갖는 이유가 여기 있다. 목적이 결함 검출 하나이기 때문이다. 대안 설계를 논의하고 싶다면 그것은 기술 검토다. 한 회의에 두 목적을 섞으면 대개 설계 토론이 시간을 다 쓰고 결함 검출은 흐지부지된다.

현대 코드 리뷰와의 관계

Microsoft 연구진 Bacchelli 와 Bird 는 Expectations, outcomes, and challenges of modern code review (ICSE 2013)에서 도구 기반 리뷰가 70~80년대 인스펙션보다 가볍고 비공식적이라고 정리하고, 결함 발견이 여전히 리뷰의 주된 동기이지만 실제 결과는 기대보다 결함과 덜 관련되며 지식 전달·팀 인식·대안 제시 같은 이점이 크다고 보고했다. Sadowski 등의 Modern code review: a case study at Google (ICSE-SEIP 2018)은 인터뷰·설문·리뷰 로그로 Google 이 리뷰를 도입한 동기와 현재 관행을 분석했다. 두 연구 모두 현대 리뷰가 “결함 검출 장치” 만으로는 설명되지 않는다는 점을 보여 준다.

측면 Fagan 인스펙션 현대 PR 리뷰
단위 산출물 전체(모듈, 설계서) 변경(diff)
동기화 회의(동기) 비동기 코멘트
역할 고정 역할 4~5개 작성자·리뷰어
준비 개인 준비 필수 대개 없음
기록 결함 분류·집계 코멘트 스레드
주된 결과 결함 검출 + 과정 데이터 지식 공유, 일관성, 일부 결함

어느 쪽이 우월하다기보다 목적이 다르다. PR 리뷰의 기초는 CS300 코드 리뷰 글에서 다뤘다.

실무 적용

언제 정형 인스펙션을 꺼내는가

  • 결함 한 건의 비용이 큰 영역: 금액 계산, 권한, 개인정보 처리, 안전 관련 로직(SE100 #089)
  • 실행으로 확인하기 어려운 산출물: 인터페이스 명세, 상태 기계 설계, DB 마이그레이션 계획
  • 같은 유형 결함이 반복 유출되는 영역: 데이터를 모아 원인을 찾는 것 자체가 목적일 때

가벼운 인스펙션을 PR 위에서 돌리는 법

회의실 없이도 핵심 요소는 살릴 수 있다.

## Inspection: settlement-fee-calculation (PR #1234)
- 모더레이터: @kim (작성자 아님)   검사자: @lee(도메인), @park(테스트 관점)
- 입구 조건: [x] 명세 링크 확정  [x] CI 통과  [x] 변경 400줄 이하로 분할
- 준비 기한: 수요일 18시까지 각자 체크리스트로 검토 (코멘트 금지, 메모만)
- 회의(30분, 목요일): @park 이 calculateFee() 흐름을 소리 내어 설명

### 체크리스트 (이 영역 전용)
- [ ] 금액은 정수(최소 화폐 단위) 또는 BigDecimal 로만 다루는가
- [ ] 반올림 모드와 위치가 명세와 같은가
- [ ] 환불·부분취소 경로에서 수수료 역산이 정확한가
- [ ] 경계값(0원, 최대 한도, 음수 입력)에 대한 테스트가 있는가

### 결함 기록
| # | 위치 | 유형 | 심각도 | 상태 |
|---|---|---|---|---|
| 1 | Fee.kt:42 | 논리-반올림 | Major | 수정됨 |
| 2 | Refund.kt:88 | 누락-경계값 | Minor | 수정됨 |
- 출구 조건: Major 0건 미해결, 재인스펙션 불필요 (모더레이터 판정)

체크리스트는 일반론(“가독성 좋은가”)이 아니라 그 영역에서 과거에 실제로 나온 결함 유형으로 채운다. 그래야 데이터가 다시 체크리스트로 돌아오는 고리가 생긴다.

남은 결함 추정: 포획-재포획

검사자 두 명이 독립적으로 준비했다면 둘의 결과로 전체 결함 수를 대략 추정할 수 있다. 생태학의 Lincoln–Petersen 추정을 빌린다.

\[\hat{N} = \frac{n_1 \cdot n_2}{m}\]
a = {"F1", "F2", "F3", "F5", "F8"}    # 검사자 A 가 찾은 결함
b = {"F2", "F3", "F4", "F8"}          # 검사자 B 가 찾은 결함
m = len(a & b)                        # 둘 다 찾은 결함
n_hat = len(a) * len(b) / m
found = len(a | b)
print(f"추정 총 결함 {n_hat:.1f}, 발견 {found}, 남은 결함 추정 {n_hat - found:.1f}")
# 추정 총 결함 6.7, 발견 6, 남은 결함 추정 0.7

겹침이 적을수록 아직 못 찾은 결함이 많다는 신호다. 검사자 간 독립성과 결함 발견 확률이 같다는 가정은 현실과 다르므로 정밀한 숫자로 믿지 말고 재인스펙션 여부를 정하는 보조 신호로만 쓴다.

흔한 오해와 함정

  • “정형 = 느리고 관료적” — 정형성의 핵심은 회의가 아니라 입출 조건과 데이터다. 비동기로도 지킬 수 있다.
  • 회의에서 고치기 — 해결책 토론이 시작되면 모더레이터가 끊고 “기록, 다음” 으로 넘긴다. 해결은 재작업 단계에서 작성자가 한다.
  • 결함 수로 사람을 평가 — 인스펙션 데이터가 작성자 평가에 쓰이는 순간 작성자는 자료를 숨기고 검사자는 결함 제기를 망설인다. 데이터는 과정 개선에만 쓴다.
  • 너무 큰 단위 — 준비 시간이 비현실적으로 길어지면 검사자는 훑어보기만 한다. 산출물을 쪼개 여러 번 인스펙션한다.
  • 체크리스트 고정 — 몇 년째 같은 체크리스트라면 결함 데이터가 되먹임되지 않고 있다는 뜻이다.

확인 문제

  1. Fagan 인스펙션에서 작성자가 낭독자를 맡지 않는 이유는?
  2. IEEE 1028 의 다섯 검토 유형 중 “결함 검출” 이 유일한 목적인 것은 무엇이고, 설계 대안을 논의하기에 적합한 것은 무엇인가?
  3. Bacchelli 와 Bird 의 연구가 현대 코드 리뷰에 대해 보고한 “기대와 결과의 차이” 를 한 문장으로 쓰라.
  4. 두 검사자가 각각 8건, 6건을 찾았고 겹친 것이 2건이다. 포획-재포획 추정으로 남은 결함 수는?

풀이

  1. 작성자는 자기 의도대로 읽어 버려 쓰인 것과 의도 사이의 차이를 드러내지 못한다. 다른 사람이 풀어 읽다 막히는 지점이 결함이나 모호함의 신호다.
  2. 인스펙션이 결함 검출 전용이고, 대안 논의는 기술 검토(또는 학습 목적이면 워크스루)가 적합하다.
  3. 결함 발견이 주된 동기였지만 실제 결과는 기대보다 결함과 덜 관련되었고 지식 전달·팀 인식·대안 제시 같은 이점이 컸다.
  4. N̂ = 8×6/2 = 24, 발견한 결함은 8+6−2 = 12 이므로 남은 결함 추정은 약 12건이다. 겹침이 적어 재인스펙션이 필요하다는 신호로 읽는다.

더 읽을거리 (References)