AI는 코드를 저렴하게 만들었지만, 리뷰를 저렴하게 만들지는 못했습니다
요약
AI가 코드 생성 비용을 낮췄지만, 코드의 안전성을 판단하고 검증하는 리뷰어의 주의력 비용은 오히려 증가했습니다. 진정한 AI 리뷰 도구는 단순한 코멘트 생성이 아닌, 리뷰어의 주의력을 효율적으로 배분하여 불확실성을 제거하는 데 집중해야 합니다.
핵심 포인트
- AI로 인해 코드 생성은 저렴해졌으나 의사결정 비용은 낮아지지 않음
- 리뷰 자동화의 과도한 출력물은 리뷰어에게 새로운 병목 현상을 야기함
- 리뷰 도구의 가치는 '주의력 대비 수익(return on attention)'으로 측정해야 함
- 단순한 요약보다 중요한 리스크를 식별하고 주의력을 적절히 배분하는 것이 핵심
AI는 제가 티켓(ticket)에 대한 설명을 마치기도 전에 패치(patch)를 생성할 수 있습니다. 또한 리뷰 요약, 우려 사항 목록, 그리고 왜 이 변경 사항이 안전한지에 대한 자신감 넘치는 문단도 만들어낼 수 있습니다.
그 어떤 것도 의사결정 비용을 낮춰주지는 못합니다.
누군가는 여전히 이 패치가 시스템에 포함되어야 하는지 결정해야 합니다. 누군가는 아주 작은 헬퍼(helper) 함수가 핫 패스(hot path)에 위치해 있다는 사실을, 무해해 보이는 스키마(schema) 변경이 오래된 클라이언트(client)를 망가뜨린다는 사실을, 혹은 테스트가 실제 세계가 아닌 모킹된(mocked) 세계를 증명하고 있다는 사실을 알아차려야 합니다.
코드 생성(Code generation)은 저렴해졌습니다. 리뷰 문장(Review prose)도 저렴해졌습니다. 하지만 판단(Judgment)은 그렇지 않았습니다.
이로 인해 엔지니어링 팀은 기묘하고 새로운 병목 현상(bottleneck)에 직면하게 되었습니다: 바로 리뷰어의 주의력(reviewer attention)입니다. 이제 희소한 자원은 또 다른 그럴듯한 변경 사항이나 그럴듯한 코멘트를 만들어내는 능력이 아닙니다. 무엇이 중요한지 이해하고, 이를 검증하며, 이를 배포(shipping)하는 것에 대한 책임을 지는 데 필요한 시간입니다.
훌륭한 AI 리뷰 도구는 더 많이 말함으로써 승리하지 않습니다. 인간을 방해할 가치가 있는 시점이 언제인지 알고 있습니다.
더 많은 코멘트가 리뷰를 악화시킬 수 있습니다
대부분의 리뷰 자동화는 출력물(output)로 측정됩니다. 스캔된 라인 수. 생성된 코멘트 수. 플래그(flagged)된 이슈 수. 작성된 요약문 등 말입니다.
이러한 수치들은 수집하기는 쉽지만, 그 자체로는 거의 쓸모가 없습니다.
코멘트는 의사결정을 바꾸거나, 리뷰어가 놓칠 법한 리스크를 노출하거나, 실제 검증 작업을 제거할 때 가치를 가집니다. 그렇지 않다면 그것은 리뷰어가 분류해야 할 또 다른 대상일 뿐입니다. 읽고, 디프(diff)와 대조해 보고, 봇(bot)이 코드를 제대로 이해했는지 결정해야 합니다. 무시하거나 다시 작성해야 합니다. 어쩌면 왜 틀렸는지 설명해야 할지도 모릅니다.
자동화는 작동했습니다. 다만 그 비용을 인간에게 떠넘겼을 뿐입니다.
봇 대 봇(Bot-on-bot) 리뷰는 빠르게 소음(noise)으로 변합니다. 한 모델이 거대한 패치를 생성하면, 다른 모델이 거대한 리뷰로 응답합니다. 그 사이에 있는 사람은 이제 검증해야 할 생성된 결과물이 하나가 아니라 두 개가 된 것입니다.
장황한 요약(Verbose summaries)은 차이점(diff)을 더 매끄러운 영어로 반복할 뿐이며, 동일한 문제를 야기합니다. 코드를 읽을 수 있는 리뷰어는 여전히 코드를 검사해야 합니다. 요약은 불확실성을 줄이지 못했습니다. 오히려 첫 번째 표현(representation)으로부터 벗어날 수 있는 두 번째 표현을 추가했을 뿐입니다.
유용한 지표를 '주의력 대비 수익(return on attention)'이라고 부릅시다. 즉, 이 신호가 소비한 주의력(attention)에 비해 얼마나 많은 불확실성을 제거했는가 하는 점입니다.
주의력을 예산처럼 취급하라
팀들은 이미 CPU, 메모리, 저장소, 그리고 API 호출에 대해 예산을 할당합니다. 리뷰어의 주의력(attention) 또한 한정되어 있고 매우 불균등하게 분포되어 있기 때문에 동일한 수준의 진지한 취급을 받아야 합니다.
모든 변경된 라인이 동일한 정밀 조사를 받을 필요는 없습니다.
200줄짜리 생성된 테스트 픽스처(test fixture)는 지루할 수는 있지만 검증하기는 쉽습니다. 반면 단 한 줄의 권한 부여(authorization) 변경 사항은 모든 주의를 집중해야 할 수도 있습니다. 차이점(diff)의 크기만으로는 어느 쪽인지 알 수 없습니다.
리뷰 도구는 더 많은 해설을 생성하는 대신, 주의력을 적절히 배분(routing)함으로써 도움을 줄 수 있습니다.
각 변경 사항에 대해, 무엇이 그것을 위험하게 만들 수 있는지 질문하십시오:
- 많은 호출자(callers) 뒤에 위치하는가?
- 패키지 또는 서비스 경계를 넘나드는가?
- 인증(authentication), 결제(billing), 영속성(persistence), 또는 정책(policy)에 영향을 미치는가?
- 이것이 깨졌을 때 어떤 테스트가 이를 감지해야 하는가?
- 런타임 동작(runtime behavior)이 어디에든 가시적으로 나타나는가, 아니면 우리는 의도(intent)만을 리뷰하고 있는가?
저는 리뷰 도구가 문단을 작성하기 시작하기 전에 이러한 질문들에 답하기를 바랍니다. 그 답변들은 인간에게 어디에 판단력을 집중해야 할지를 알려주는 것이지, 판단력을 대체하는 것이 아닙니다.
그 차이는 중요합니다. 최종 판결자가 되려는 AI 리뷰어는 모든 것에 대해 옳아야 합니다. 반면 주의력을 할당하려는 리뷰 시스템은 위험 표면(risk surface)을 더 작고 읽기 쉽게 만들기만 하면 됩니다.
그것이 소프트웨어가 수행하기에 훨씬 더 나은 역할입니다.
구조적 위험이 라인 수보다 중요하다
code-review-graph 뒤에 있는 문서화된 모델은 유용한 예시입니다. 이 모델은 함수, 클래스, 임포트(imports), 호출(calls), 상속(inheritance), 그리고 테스트의 로컬 구조 지도(structural map)를 구축합니다. 코드가 변경될 때, 리뷰 컨텍스트(context)는 차별화되지 않은 저장소의 조각이 아니라 호출자, 의존자(dependents), 그리고 영향을 받는 경계들을 포함할 수 있습니다.
저는 이 프로젝트를 테스트하지 않았으며, 성능 수치는 자체적인 벤치마크 결과입니다. 흥미로운 부분은 속도에 대한 주장이 아니라 모델입니다.
diff(차이점)는 고립된 문서가 아닙니다. 그것은 그래프(graph)에 대한 편집입니다.
변화를 그런 방식으로 바라보기 시작하면, 리뷰 우선순위는 덜 임의적이게 됩니다. 20개의 의존자(dependents)를 가진 작은 함수는 거대한 리프 컴포넌트(leaf component)보다 더 많은 주의를 필요로 할 수 있습니다. 타입(type) 변경은 패키지 외부의 소비자(consumers)를 그래프가 보여주기 전까지는 무해해 보일 수 있습니다. 테스트 파일은 단순히 변경되었기 때문에 중요한 것이 아니라, 영향을 받는 경로를 커버하는 유일한 증거이기 때문에 중요합니다.
구조적 컨텍스트(Structural context)는 또한 AI에게 더 좁은 과업을 부여합니다. "이 저장소를 리뷰해줘"는 토큰을 낭비하고 일반적인 조언을 생성하라는 초대와 같습니다. "이 변경된 함수, 호출자(callers), 영향을 받는 테스트, 그리고 이 함수가 가로지르는 경계(boundary)를 검사해줘"는 리뷰 가능한 작업입니다.
목표는 최대의 컨텍스트(context)를 확보하는 것이 아닙니다. 리스크(risk)를 보존할 수 있는 최소한의 컨텍스트를 찾는 것입니다.
결정 옆에 증거를 두십시오
리스크 라우팅(Risk routing)은 리뷰어를 적절한 위치로 안내합니다. 다음 작업은 그곳에 증거를 유지하는 것입니다.
라인에 고정된 피드백(Line-anchored feedback)은 패치(patch)에 대한 분리된 에세이보다 여전히 더 유용합니다. Diffsmith의 제품 인터페이스는 간단한 예시입니다. 코멘트가 로컬의 변경된 라인에 부착되며, 수정 루프(correction loop)로 다시 흘러 들어갈 수 있습니다. 앵커(anchor)가 코멘트의 정확성을 증명하는 것은 아닙니다. 하지만 우려 사항을 찾아내고 조치하는 비용을 줄여줍니다.
좋은 리뷰 증거는 짜증스러울 정도로 구체적이어야 합니다:
- 이 라인은 권한 결정(authorization decision)을 변경합니다
- 이 호출자(caller)는 nullable 값을 전달합니다
- 이 테스트는 해피 패스(happy path)는 커버하지만 실패 모드(failure mode)는 커버하지 않습니다
- 이 런타임 트레이스(runtime trace)는 의도된 상태 전이(state transition)와 모순됩니다
- 이 의존성 경계(dependency boundary)는 롤백(rollback)을 더 어렵게 만듭니다
구체성(Specificity)은 장황함(verbosity)과 같지 않습니다. 정확한 문장 하나와 관련 테스트 결과가 일반화된 주의 사항 다섯 문단보다 더 나을 수 있습니다.
증거는 또한 자신의 한계에 대해 정직해야 합니다. 의존성 그래프(dependency graph)가 런타임 동작(runtime behavior)을 증명할 수는 없습니다. 통과하는 단위 테스트(unit test)가 제품의 의도(product intent)를 확정할 수 없습니다. 모델의 자신감 있는 설명이 아키텍처 소유권(architecture ownership)을 대체할 수는 없습니다. 이 도구는 자신이 무엇을 알고, 무엇을 추론했고, 무엇이 여전히 사람의 도움이 필요한지 보여주어야 합니다.
만약 출력이 이러한 경계를 숨긴다면, 리뷰어는 그것들을 재발견해야 합니다. 그러면 주의력 예산(attention budget)이 사라집니다.
5가지 질문으로 중단 테스트하기
자동화된 검토 신호가 사람에게 도달하기 전에, 그 신호가 중단을 정당화하도록 만드세요.
- 이것이 누군가의 어떤 결정을 내리는 데 도움이 될까요?
"승인(Approve), 테스트 요청(request a test), 호출자 검사(inspect a caller), 또는 변경 차단(block the change)\
팀들이 더 많은 자동화된 리뷰어(automated reviewers)를 추가하는 방식으로 대응할 때, 대기열(queue)이 다시 늘어날 수 있습니다. 더 많은 봇(bot)은 더 많은 결과물(findings)을 만들어냅니다. 더 많은 결과물은 더 많은 분류 작업(triage)을 요구합니다. 병합 결정(merge decision)은 완고하게 인간의 영역으로 남아 있는 동안, 시스템은 바빠 보이기만 합니다.
그러니 결정 범위(decision surface)를 압축하십시오. 판단(judgment)이 사라진 척하지 마십시오.
폭발 반경(blast radius)을 매핑하십시오. 경계 위험(boundary risk)의 순위를 매기십시오. 가장 작고 유용한 증거를 보여주십시오. 피드백을 변경 사항(change)에 부착된 상태로 유지하십시오. 신호(signal)가 실제 결정을 바꿀 수 있을 때만 사람을 방해하십시오.
AI는 말하는 비용을 저렴하게 만들었습니다. 리뷰 시스템은 입을 다무는 법을 더 잘 배워야 합니다.
출처 노트
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기