Claude Code 팀의 코드 리뷰 방식
요약
Anthropic의 Claude Code 팀은 급증하는 코드베이스와 변경 사항을 효율적으로 검토하기 위해 기존의 수동적인 코드 리뷰 방식을 자동화 및 지속적 검사 방식으로 혁신했습니다. 이들은 대부분의 읽기 작업을 기계로 옮기고, 인간의 주의력을 오직 고차원적인 문제 해결에 집중시키도록 최적화하는 데 초점을 맞추고 있습니다.
핵심 포인트
- 코드 리뷰는 수동적 관문에서 지속적이고 자동화된 검사 방식으로 변화함.
- Anthropic은 PR당 인간 개입을 최소화하고, 롤백 및 사고 발생률 증가를 방지하는 것을 목표로 함.
- 대부분의 일상적인 오류 수정은 사람이 보기 전에 Claude에 의해 자동으로 처리됨.
- 인간의 시간과 주의력은 오직 기계가 해결할 수 없는 문제에만 보존되어야 함.
에이전트가 생성하는 방대한 양의 코드를 어떻게 검토할까요? Claude Code 팀에서는 높은 커버리지와 깊은 리뷰를 거치면서, 되돌리거나(reverts) 사고(incidents)를 일으키지 않는 최소한의 인간 검토 시간을 최적화하기 시작했습니다.
이전에 저희는 Claude가 Claude Code 자체 코드의 약 90%를 작성한다고 말씀드린 적이 있습니다. 그렇다면 우리가 생산하는 양만큼 코드를 어떻게 검토할까요? 아무도 더 이상 코드를 읽지 않는 걸까요? 그리고 무언가 문제가 생기면 누가 잡아낼까요?
본 게시물에서는 Claude Code 팀의 코드 리뷰 흐름과 그것이 어떻게 진화해 왔는지 다룹니다. 6월부터 9월까지, Claude Code의 코드베이스에 병합된 풀 리퀘스트(pull requests)는 두 배 이상 증가했지만, 되돌려야 하는 비율은 40% 이상 감소했습니다.
저희가 리뷰를 없앤 것은 아닙니다. 하지만 대부분의 읽기 작업(reading)을 기계로 옮기고, 인간의 시간과 주의력에 최적화했으며, 실수를 빠르고 쉽게 되돌릴 수 있도록 막대한 투자를 했습니다.
에이전트들이 코드를 작성할 때, 변경 사항의 수는 빠르게 늘어납니다. Anthropic의 모노레포(monorepo)에서는 하루에 병합되는 변경 사항 수가 5월 약 2,500개에서 올해 9월에는 30,000개가 넘는 수준으로 증가했습니다.
Claude Code는 모노레포와 분리된 자체 저장소에 존재하지만, 여기도 많은 압박을 받고 있습니다. 이렇게 빠르게 배포할 때는 수동적인 라인별 코드 리뷰가 엄청나게 어렵거나 불가능합니다.
코드 리뷰는 두 가지 역할을 합니다:
이 기사는 주로 문제점을 찾고 수정하는 첫 번째 역할에 초점을 맞추지만, 두 번째 역할은 나중에 다시 다루겠습니다.
저희는 '사람이 코드를 읽었는가?'라는 질문을 '이 변경 사항에서 무엇이 잘못될 수 있으며, 어떤 검사(자동화된 것인지 인간의 것인지)가 그것을 잡아내는 것이 적절한지'에 대한 부정확한 대용 지표라고 생각합니다?
이러한 질문은 또한 리뷰가 일어나는 시기까지 변화시켰습니다. 이전에는 리뷰가 길 끝의 관문과 같았습니다: 코드를 작성하고, PR을 열고, 동료를 기다리는 것이었습니다.
이제 검토는 사용자가 작성하는 동안 맞춤법 검사기처럼 지속적으로 실행됩니다. 대부분의 변경 사항은 사람이 살펴보기 전에 Claude에 의해 최소 한 번 이상 검토되고 수정되었습니다. 이를 통해 대부분의 일상적인 실수를 잡아내고, 팀의 주의를 더 높은 수준의 질문과 심층 분석에 집중할 수 있도록 절약해 줍니다.
우리는 인간의 시간과 주의력을 오직 인간만이 해결할 수 있는 문제에만 보존하고, 자동화된 검사가 나머지 부분을 처리하도록 만들고자 합니다. 현재 변경 속도로 볼 때도 여전히 인간이 할 수 있는 엄청난 양의 작업이 남아 있으며, 저희 팀은 거의 매일 새로운 독창적인 과제들을 마주합니다.
인간의 시간은 검토 비용의 양쪽 면을 모두 다룹니다. 즉, 사람들이 검토하는 데 쓰는 시간과 나쁜 코드가 고장 낼 때 그것을 수정하는 데 쓰는 시간을 말합니다. 전자를 줄이더라도 후자의 시간에 그 시간이 나타난다면 도움이 되지 않습니다.
따라서 목표는 Claude Code 레포지토리(CLI, 데스크톱 및 웹 앱, 모바일 앱)의 대부분의 풀 리퀘스트(PR)가 한 명의 인간 개입만으로 병합되는 것입니다. 이 인간은 작성자일 수 있으며, 롤백이나 사고 발생률이 증가해서는 안 됩니다. 인간 시간을 측정하기 위해 PR당 인간 승인 건수(중앙값 및 95번째 백분위수), 인간 코멘트 수, 그리고 PR이 사람에게 대기하는 시간 등을 추적합니다. 롤백 및 사고율은 안전장치입니다. 만약 이들이 증가한다면, 우리는 인간의 시간을 절약한 것이 아니라 단지 이동시킨 것일 뿐입니다.
엔지니어의 노트북(또는 Slack에서 Claude 세션)에서 발생하는 일반적인 변경 사항은 여러 계층의 코드 검토를 거칩니다.
대부분의 검토는 PR이 생성되기 전에 이루어집니다. 우리는 Claude가 실행할 수 있는 것—예를 들어 테스트, 빌드 또는 디자인과 비교할 스크린샷—을 제공하고, 완료되었다고 말하는 대신 그 출력을 보여달라고 요청합니다. 그런 다음 서브 에이전트가 새로운 컨텍스트로 diff(차이점)를 검토합니다. 이 두 가지 습관은 저희의 모범 사례 가이드에서 비롯된 것입니다.
PR을 열기 전에, 우리 중 다수는 몇 가지 내부 스킬도 실행합니다. 하나는 버그를 찾고, 하나는 diff를 단순화하며, 또 다른 하나는 끝단 간(end to end) 동작을 확인합니다. UI 변경 사항 또한 저희의 디자인 가이드라인에 따라 검사됩니다.
Claude Code를 만든 Boris Cherny는 Claude에게 자신의 작업을 검증할 수 있는 방법을 제공하는 것이 좋은 결과를 얻기 위해 가장 중요한 것일 수 있다고 언급했습니다. 그는 이것이 최종 결과물을 두세 배 더 좋게 만든다고 추정하며, “검증은 도메인마다 다르게 보입니다. 간단하게 bash 명령을 실행하거나, 테스트 스위트를 실행하거나, 브라우저 또는 휴대폰 시뮬레이터에서 앱을 테스트하는 것일 수 있습니다.”라고 썼습니다.
자동 검토자가 계속 같은 것을 지적하면, 우리는 근본 원인(source)에서 수정합니다. 즉, 스킬 내에, 린트 규칙(lint rule)으로, 또는 다음과 같은 안내 파일 업데이트를 통해 합니다:
CLAUDE.md
이 파일은 Claude에게 프로젝트가 무엇인지 알려줍니다: 스택, 컨벤션, 목표 및 비목표 등을 말이죠. 모든 검토는 이 파일을 로드하므로, 대규모 코드베이스에서는 짧게 유지하고 거기서 다른 문서로 연결합니다. 검토자는 또한 컨벤션을 위반하는 코드를 지적하고, 해당 라인을 구식으로 만드는 변경 사항을 수정합니다.REVIEW.md
이 파일은 코드 소유자(code owners)가 작성하며, 리뷰어에게 자신들의 코드 부분에서 무엇이 중요한지 알려줍니다. 우리는 리뷰어가 실제로 그것을 따르는지 별도로 확인합니다. 좋은 파일들은 짧습니다. 그들은 해당 리포지토리에서 실패가 어떻게 보이는지 말하고 (문서의 경우
연구 프리뷰를 출시했을 때, 실질적인 검토 의견을 받는 내부 PR의 비율은 16%에서 54%로 증가했습니다. 1,000줄이 넘는 대부분의 PR은 발견 사항(findings)을 얻고, 작은 PR들은 대부분 문제없이 통과합니다. 관리자들은 각 리포지토리별로 Quick, Standard, 또는 Deep 설정을 할 수 있습니다. Deep 설정은 하나의 놓친 버그가 추가 검토 시간보다 더 큰 비용이 발생할 때 가치가 있습니다.
발견 사항은 사람이 검토하기 전에 다른 에이전트들에 의해 검증됩니다. 여러 에이전트들이 동시에 버그를 찾습니다. 그런 다음 별도의 그룹이 각 발견 사항에 대해 투표하며, 충분한 동의가 있어야만 게시됩니다. 스타일, 진단(diagnostics), 또는 정리(cleanup)에 관한 발견 사항은 제외됩니다. 저희는 이러한 필터를 유지하기 전에 자체 PR을 대상으로 A/B 테스트를 진행했습니다. 남은 것들은 심각도별로 정렬된 인라인 댓글로 표시됩니다. 각 항목에는 Important, Nit, 또는 Pre-existing 태그가 붙어 있어, PR이 도입하지 않은 버그가 작성자의 잘못처럼 보이지 않게 합니다.
모든 발견 사항에 답변해야 합니다. 수정하거나 이유와 함께 스레드를 해결해야 합니다. 종종 에이전트가 밤새 수정을 진행하기 때문에, 작성자는 이미 다른 라운드를 거친 PR로 돌아오게 됩니다.
보안 검토도 별도의 자동화된 검토를 받습니다. 버그 검토나 보안 검토에서 발견된 발견 사항 중 하나라도 해결되지 않은 상태라면 PR은 병합(merge)될 수 없습니다. 수정하거나 짧은 이유와 함께 스레드를 닫아 거짓 양성(false positive)을 해제할 수 있습니다.
만약 나중에 커밋이 문제를 수정하면, 해당 발견 사항은 자동으로 사라집니다. 오픈 소스 보안 검토 GitHub Action이나 /security-review 명령어로 동일한 설정을 할 수 있습니다. 설정 방법은 Claude Code의 자동화된 보안 검토에서 다루고 있습니다.
일반적으로는 린트(lint), 타입 체크, 모든 플랫폼에서의 테스트, 그리고 빌드가 진행됩니다. (이 볼륨에 대한 CI 스케일링에 대해서는 여기에서 작성했습니다.) 일반적인 CLI 풀 리퀘스트는 누군가 검토하기 전에 수십 개의 검사를 실행할 수 있습니다. PR 템플릿에는 변경 사항이 어떻게 테스트되었는지와 어떻게 되돌릴 수 있는지에 대한 질문이 포함되어 있습니다. Claude가 이 내용을 채울 수는 있지만, 변경을 요청한 사람이 최종적으로 승인해야 합니다.
문서 수정 및 자동 업데이트 변경은 서로 다른 위험도를 가지므로, 각각 다른 검토를 거칩니다.
| 위험도 | 예시 | 사람 승인 필요 여부 |
|---|---|---|
| 낮음 (Low) | 문서(Docs), 복사본(copy), 내부 전용 기능, 플래그 뒤의 추가 변경 사항 | 자동화된 검토와 보안 점검이 통과되면 필요 없음 |
| ... | ||
| 변경 사항이 등급을 결정하며, 작성자가 아닙니다. 분류기(classifier)가 변경 사항을 읽어 위험도를 선택합니다. 두 번째 분류기는 해당 특정 변경 사항이 등급상 필요하지 않더라도 다른 사람의 승인이 필요한지 묻습니다. 일부 경로는 항상 사람이 필요하고, 소유자(owners)가 민감하다고 지정한 모든 것과 CI 워크플로우 파일도 마찬가지입니다. |
신뢰할 수 있는 작성자만 가벼운 경로를 이용할 수 있습니다. 리포지토리의 신뢰 목록에 있는 작성자들, 주로 해당 팀이 가벼운 경로를 이용합니다. 다른 사람은 모두 두 번째 사람의 승인이 필요합니다. 에이전트(agent)의 승인은 결코 사람의 승인으로 간주되지 않습니다. 자동화된 검토는 낮은 위험도의 변경 사항을 통과시킬 수 있지만, 사람이 필요한 슬롯을 채울 수는 없습니다.
변경 사항을 요청한 사람이 책임을 집니다. 에이전트가 작성한 PR의 경우, 에이전트를 지시한 사람이 필수 검토자 중 한 명으로 간주되며, 마치 그들이 직접 코드를 입력한 것과 같습니다.
승인은 특정 커밋 하나를 다룹니다. 시스템이 보증할 수 없는 새로운 커밋(예: 에이전트의 푸시 또는 누군가 수동으로 해결한 병합)이 들어오면, 승인을 다시 받아야 합니다.
병합 대기열(merge queue)은 변경 사항을 적용하여 main 브랜치에 대한 모든 검사를 재실행하므로, 개별적으로 통과하는 두 개의 PR이 손상된 main으로 결합될 수 없습니다. 새로운 동작은 보통 Anthropic 직원들에게 먼저 플래그 뒤에서 배포되며, 우리의 과도한 사용은 사용자보다 먼저 회귀(regressions)를 표면화시키는 경우가 많습니다. 공개 릴리스는 latest 채널로 먼저 이동하고, stable 채널이 그 뒤를 따릅니다.
일부 실수는 여전히 통과할 수 있으므로, 마지막 단계는 이를 빠르게 포착하는 것입니다. 플래그가 해제되면 배포 없이 비활성화됩니다. Claude Code는 매주 온콜(on-call) 로테이션을 운영하며, 인시던트 검토에서는 어떤 계층이 이 문제를 잡아냈어야 하는지 묻습니다.
나쁜 병합(merge)을 발견하는 것은 작성자, 온콜 담당자뿐만 아니라 되돌리기(revert) 및 인시던트 대시보드에 의존합니다. 저희는 이러한 수치가 변동할 때 승인 절차를 강화하는 회로 차단기(circuit breakers)가 아직 없습니다. 엔지니어들은 더 많은 코드가 사람 개입이 없는 병합으로 이동하기 전에 이것들을 원합니다.
한 동료는 속도를 늦추면 오류율이 낮아진다고 말했지만, 그것은 주로 모든 것을 적게 하기 때문입니다. 저희는 문제점을 발견하고 수정하는 속도가 빨라지는 것을 더 선호합니다.
저희의 코드 리뷰 프로세스는 끊임없이 순환하며 개선되고 있습니다.
모든 인시던트는 이제 평가(eval) 대상입니다. 팀은 인시던트를 유발했던 과거 PR을 수집하고, 그에 대한 수정 및 되돌리기를 거친 후, 해당 코드를 아는 엔지니어들이 각 버그와 그것이 존재했던 위치를 확인했습니다. 리뷰어는 이 세트(set)를 매일 실행합니다.
저희는 댓글을 통해 사람들이 무엇을 하는지를 관찰하여 노이즈를 측정합니다. 많은 '버그가 아닌 것'들을 지적하는 것을 꺼리지 않는다면 더 많은 버그를 잡아내는 것이 쉽기 때문에, 저희는 이에 대한 점검이 필요합니다. 리뷰어가 남긴 모든 댓글은 PR 작성자가 어떻게 응답했는지에 따라 분류됩니다: 수정했다고 했는지, 틀렸다고 했는지, 동작이 의도적이라고 했는지, 아니면 중요하지 않다고 결정했는지입니다. 또한, 저희는 깨끗하다고 알려진 PR을 대상으로 리뷰어를 실행하여, 이로 인해 누군가가 유해한 변경을 할 수 있게 만들었을 만한 내용을 보고하는 빈도를 계산합니다. 저희의 우선순위는 명문화되어 있으며, 첫째는 실제 버그를 포착하고 둘째는 리뷰 라운드를 줄이는 것입니다.
노이즈는 작성자가 에이전트(agent)일 때 더 많은 비용을 초래합니다. 사람은 사소한 문제점(nit)을 몇 초 만에 무시할 수 있습니다. 하지만 에이전트는 그것을 수정하므로, 또 다른 커밋과 또 다른 리뷰 라운드를 의미하게 됩니다.
리뷰는 수렴해야 합니다. 에이전트 작성자와 에이전트 리뷰어는 서로를 끝없이 바쁘게 만들 수 있습니다. 한 CLI PR은 그 작성자가 중단하기 전까지 하룻밤 사이에 50회 이상의 리뷰와 수정 과정을 거쳤습니다.
저희가 리뷰어가 계속해서 플래그 지정했던 내용에 대해 git blame을 실행했을 때, 약 59%는 리뷰어의 첫 번째 검사부터 존재했던 코드였습니다. 리뷰어는 거의 새로운 버그를 발견하지 못했고, 매 라운드마다 몇 개의 오래된 버그만 더 찾아내고 있었습니다.
우리가 스스로 상황을 악화시켰습니다. 각 패스(pass)마다 새로운 것을 포착하기 때문에, 기본적으로 여러 라운드를 실행하는 것에 익숙해졌기 때문입니다. 이는 위험도가 높은 변경 사항에는 가치가 있을 수 있지만, 모든 PR(Pull Request)에 해당되는 것은 아닙니다. 팀은 이제 재현율(recall)과 함께 라운드-대-패스(rounds-to-pass), 그리고 변경된 재검토(changed re-review)를 추적합니다:
리뷰 에이전트들은 또한 기존 코드를 매일 밤 실행하여, 오래된 버그가 다른 곳에 나타나기 전에 포착하는 데 도움을 줍니다.
숙련된 엔지니어를 깊은 작업(deep work)에서 빼내서 일상적인 실수를 잡는 것은 자동화된 리뷰보다 훨씬 많은 비용이 듭니다. Anthropic에서는 우리의 업무가 모든 diff를 읽는 것에서, 기계가 잘 못하는 결정으로 이동했습니다:
코드 리뷰의 두 번째 역할은 항상 코드베이스에 대한 이해도를 확산시키는 것이었습니다. 팀원의 diff를 읽는 것은 무엇이 변경되었고 조각들이 어떻게 맞물리는지 배우는 방법입니다. 만약 기계가 대부분의 읽기를 한다면, 누가 코드를 배울 수 있을까요?
우리는 이것에 대한 공식적인 프로세스를 가지고 있지 않습니다. 팀 누구도 Claude Code 전체에 대한 완전한 정신 모델(mental model)을 머릿속에 유지하고 있지는 않으며, 우리는 아무도 그럴 필요가 없다고 생각합니다. 누군가 코드베이스의 특정 부분을 이해하고 싶어 할 때, 그들은 Claude에게 정확히 그 슬라이스(slice)에 대한 설명서(explainer)를 작성해 달라고 요청합니다. 이는 몇 분밖에 걸리지 않으며 오늘날의 코드를 반영합니다.
우리 중 일부는 한 단계 더 나아가서, 해당 코드 부분을 시각화하고 그 사람이 배우는 방식을 가르칠 수 있는 작은 아티팩트(artifact)를 Claude가 만들도록 합니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 HN Claude Code의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기