큰 diff를 뇌정지 없이 리뷰하는 법 — PR #1148(PPI-1348) 예시

마지막 업데이트 2026-10-02

2026-10-02 · 예시 커밋 0f94a87a [PPI-1348] fix: HC 모드 입력 전사 실패 시 자동 복구 (#1148) · 8파일 +334/−33

요약. diff를 파일 순서가 아니라 데이터가 흐르는 순서(producer → consumer)로 읽는다. 그 전에 PR 본문으로 가설 한 문장을 세우고, 파일을 역할별로 나눠 읽는 강도를 정하고, 테스트 이름으로 시나리오 목차를 얻는다. 리팩터링(이름 변경·추출)은 --color-moved로 걸러내고, 각 hunk에서는 "언제 안 도는가"만 묻는다. 그러면 334줄짜리 PR이 새 함수 3개로 줄어든다. LLM에게 데이터 흐름 지도를 먼저 받는 것도 좋지만, 지도이지 답이 아니다 — 화살표마다 파일:줄 근거와 "안 도는 조건"을 요구하고 직접 대조한다.

1. 6단계 한눈에

① 가설PR 본문만 읽고 한 문장
② 분류--stat → 역할별 강도
③ 테스트명시나리오 목차
④ 흐름순producer → consumer
⑤ 분리리팩터링 걸러내기
⑥ 안 도는 조건억제 분기 대조
과부하 방지 규칙: 머릿속에는 미해결 질문을 한 번에 하나만 둔다. 나머지는 메모장에 적고 넘어간다.

2. ① 코드를 열기 전에 가설 한 문장

PR 본문(커밋 메시지 bullet 6개)만 읽고 이렇게 정리한다.

"vendor가 턴을 조용히 버리던 곳에서 이벤트를 쏘고, agent.py가 그걸 받아 '(판독 불가)' 되묻기를 한다."

이후 읽는 모든 코드는 이 문장을 확인하거나 반박하는 용도로만 쓴다. 가설 없이 diff를 열면 줄마다 "이게 왜 필요하지?"가 쌓여 정지한다.

3. ② --stat으로 역할별 분류 → 읽는 강도 결정

git show --stat 0f94a87a
역할파일줄읽는 강도
계약 (새 이벤트)vendor/.../events.py, __init__.py, agent_session.py+19훑기
발생 지점vendor/.../agent_activity.py+12정독
소비 + 복구agent.py+107/−31정독 (리팩터링분 제외)
가드input_gate.py+8정독
명세tests/test_turn_terminalization.py 외 1+188/−2테스트 이름만 먼저

전체의 절반 이상(테스트 188줄)은 처음엔 이름만 읽으면 되고, vendor 4파일 중 3개는 배선이라 훑기만 하면 된다.

4. ③ 테스트 이름 = 시나리오 목차

git show 0f94a87a -- 'apps/livekit-agent/tests/*' | grep '^+.*def test'
테스트 (test_half_cascade_…)의미
provider_failure_delivers_unreadable_recovery_once정상 복구, 딱 1회
provider_failure_before_local_commit_waits_for_commit이벤트가 로컬 commit보다 먼저 오는 순서 역전
provider_failure_without_eligible_turn_skips_recovery억제 조건
superseded_vendor_turn_failure_skips_resumed_epoch재개된 턴의 정상 발화를 덮어쓰지 않음

이 4줄이 이 PR이 다루는 경우의 수 전부다. 코드를 읽다가 이 목록에 없는 분기를 만나면 그게 리뷰 포인트다.

5. ④ 데이터 흐름 순서로 읽기 (producer → consumer)

events.py          UserInputTranscriptionFailedEvent 정의            ← 계약
   ↓
agent_activity.py  턴 폐기 직전 emit
                   조건: input_turn_id 있음 · not skip_reply
                         · not session._closing · rt_session 교체 안 됨
   ↓
agent.py           @session.on("user_input_transcription_failed")
                   _on_user_input_transcription_failed
                   → vendor input_turn_id를 로컬 turn_id로 매핑
                   → superseded면 중단 (input_gate.is_latest_vendor_turn)
   ↓
agent.py           _maybe_schedule_provider_final_fallback
                   → 로컬 turn_committed_at 전이면 보류, commit 후 1회만 예약
   ↓
agent.py           _run_provider_final_fallback
                   → _deliver_unreadable_recovery (기존 함수 재사용)
git show 0f94a87a -- '*events.py' '*agent_activity.py'     # 계약 + 발생
git show 0f94a87a -- apps/livekit-agent/input_gate.py      # 가드
git show 0f94a87a -- apps/livekit-agent/agent.py           # 소비 + 복구

파일 목록은 알파벳순이라 agent.py(소비자)가 먼저 나오고 events.py(계약)가 마지막에 나온다. 그 순서대로 읽으면 "이 이벤트는 어디서 오지?"를 머리에 들고 100줄을 읽게 된다.

6. ⑤ 리팩터링과 동작 변경 분리

agent.py 변경 중 동작이 바뀌지 않는 기계적 변경:

git show 0f94a87a --color-moved=dimmed-zebra -w -- apps/livekit-agent/agent.py

옮겨지기만 한 줄은 흐리게 표시된다. 진하게 남는 건 사실상 _on_user_input_transcription_failed, _maybe_schedule_provider_final_fallback, _run_provider_final_fallback 새 함수 3개와 정리 루프 몇 줄이다.

추출된 헬퍼는 "원래 두 곳과 정확히 같은가"만 확인하면 된다. 이 PR에서는 initiator 문자열이 인자로 바뀐 것 외에 동일하다.

7. ⑥ hunk마다 "언제 안 도는가"

버그는 대부분 억제 조건에 숨는다. PR 본문의 억제 목록을 코드 위치와 1:1로 대조한다.

PR 본문의 억제 조건코드
skip_reply · 세션 종료 · rt_session 교체agent_activity.py emit 조건 4개
중복turn_id in unreadable_recovery_tasks, turn_id in stt_fallback_turn_ids
새 발화 (VAD 재진입)재진입 처리에서 pending_provider_final_failure_turn_ids.discard
수동 인터럽트_stt_no_final_turn_is_eligible(cancellation_generation=…)
세션 종료 (agent 측)stale 정리 루프에 새 set 추가
재개 턴 보호superseded = not is_latest_vendor_turn

한쪽에만 있는 항목이 나오면 그게 질문거리다. 새 상태 컨테이너(pending_provider_final_failure_turn_ids)가 생기면 add·discard·정리 지점을 전부 찾는다 — 하나라도 빠지면 누수나 유령 복구가 된다.

8. LLM에게 흐름 지도를 먼저 받는다면

좋은 출발점이지만 지도이지 답이 아니다. 그냥 "흐름 만들어줘"라고 하면 생기는 문제:

요청 템플릿

PR #1148 diff를 리뷰하기 전에 데이터 흐름 지도를 만들어줘.
1. producer → consumer 순서로 화살표 체인. 각 화살표에 파일:줄 근거 필수
2. 각 단계마다 "이 경로가 안 도는 조건(early return/가드)"을 전부 나열
3. 동작 변경 hunk와 순수 리팩터링(이름 변경·추출) hunk를 분리
4. 테스트 이름 → 어떤 분기를 검증하는지 매핑
5. 확신 없는 연결은 "추정"으로 표시

1번(줄 근거)과 2번(안 도는 조건)이 핵심이다. 줄 근거가 있어야 화살표를 직접 열어 대조할 수 있고, 안 도는 조건 목록이 있어야 7절처럼 PR 본문과 대조해 빠진 것을 찾을 수 있다.

사용 순서

  1. 위 템플릿으로 지도를 받는다.
  2. 화살표마다 해당 줄을 직접 열어 확인한다. 틀린 화살표가 하나라도 있으면 지도 전체를 의심한다.
  3. 지도와 코드가 다른 곳, "추정" 표시된 곳에 리뷰를 집중한다.

9. 도구

명령 / 스킬용도
git show --stat <sha>② 역할 분류
git show <sha> -- <path>④ 흐름 순서대로 파일 단위 열기
--color-moved=dimmed-zebra -w⑤ 이동·공백 변경 흐리게
/diff-walkthrough 1148한 파일씩 턴테이킹으로 함께 보기
/diff-summary 0f94a87adiff + 변경 목적 요약 (2·5번 템플릿 항목은 요청 시 추가)
/pr-diff-review 1148시각화 리뷰 문서 생성

관련 문서