흔한 코드 리뷰

- const userCount = users.length
+ const userCount = users?.length ?? 0

"?? 0 으로 안전하게 처리"

이게 잘못된 건 아닙니다. 다만 가장 큰 가치가 아닙니다.

더 가치 있는 코멘트

// users 배열이 null일 수 있는 케이스는 OAuth race condition.
// ?? 0으로 처리하면 카운트가 잘못 표시되어 throw로 변경.

이 리뷰는 코드가 아니라 결정에 대해 묻습니다.

  • 왜 ?? 0이 아니라 throw인가?
  • race condition을 코드로 처리하지 않고 호출자에게 넘기는 결정의 근거는?
  • 다른 race condition도 같은 패턴으로 처리해야 하는가?

코드는 시간이 지나면 자명해질 수 있습니다 (또는 리팩토링됩니다). 결정의 근거는 시간이 지나면 사라집니다.

코드 리뷰 우선순위

  1. 결정의 이유: "왜 이 방향?" — 가장 가치 있음
  2. 놓친 케이스: "이 입력에서는?" — 사용자 영향 큼
  3. 호출자 영향: "이 변경이 X에 어떻게?" — side effect
  4. 유지보수성: "6개월 후 읽기 어렵다" — 중간
  5. 스타일·네이밍: "이름 X가 더 명확" — 가장 낮음 (linter 자동)

좋은 리뷰의 시그널

  • 코드 라인 자체보다 PR 본문 / commit 메시지에 대한 코멘트가 많은가
  • "왜 이거 아닌가?"가 "이거 잘못됨"보다 많은가
  • approver가 코드 변경 외에 "이 코드가 사라질 때를 대비한 테스트가 있는가" 같은 영속성 질문을 하는가

함정

  • 결정 질문은 작성자가 답하기 어려움 → 리뷰 시간 ↑. 그래서 PR 본문에 미리 결정 근거 적기.
  • "다 잘 보였어요" 리뷰는 가치 0. 작성자에게 "결정 근거"를 묻지 않은 신호.
  • 사소한 스타일 코멘트 5개 = 가치 있는 결정 코멘트 1개 안 됨.

핵심

코드 리뷰는 코드를 보는 게 아니라 이 변경이 만든 결정을 보는 일이다.

관련

/notes/codex-competition — 리뷰 코멘트가 부족할 때 외부 에이전트와 경쟁시켜 결정의 사각지대를 노출 /notes/coderabbit-cubic-double-review — 자동 리뷰는 결정보다 코드만 봄, 사람 리뷰는 결정 자리