코드 리뷰를 6단계로 나누었더니 AI와 인간의 분업이 보였다
요약
AI에게 로직 검토를 전적으로 맡겼을 때 발생한 버그 사례를 통해, AI와 인간의 명확한 역할 분담 필요성을 역설합니다. 기존의 3층 모델보다 세분화된 '6단계 코드 리뷰 모델'을 제안하며, 문제의 성질에 따라 AI와 인간의 개입 비율을 조절하는 방법론을 다룹니다.
핵심 포인트
- AI가 놓칠 수 있는 엣지 케이스와 로직 오류에 대한 인간의 비판적 검토가 필수적임
- 코드 리뷰를 Format, Lint 등 단계별로 세분화하여 AI와 인간의 경계선을 명확히 해야 함
- Format과 Lint는 외관과 의미의 차이로 구분하며, 이를 자동화하여 리뷰어의 소모를 방지해야 함
- 단계가 내려갈수록 정답이 일의적이지 않은 문제로 변하며 인간의 역할이 중요해짐
저는 처음에 Logic 계층을 AI에게 맡겼다가 3개의 버그를 통과시켰습니다.
엣지 케이스 (Edge Case) 판정 누락, 빈 배열 (Empty Array) 처리 실수, 외부 API의 재시도 (Retry) 조건 불일치. CodeRabbit도 Copilot도 지적하지 않았고, 저 자신도 "AI가 확인했으니 괜찮겠지"라고 생각하며 Approve를 눌렀습니다. 운영 환경에서 데이터 10개가 어긋나 있다는 것을 깨달은 것은 출시 3일 후였습니다.
숫자상으로는 작은 버그였습니다. 하지만 무서웠던 것은 "내 리뷰 판단을 신뢰할 수 없게 되었다"라는 감각입니다. AI가 놓친 것은 어쩔 수 없다 하더라도, 저 자신이 코드를 읽고 Approve를 눌렀다는 사실이 남습니다. 무엇을 보았고, 무엇을 놓쳤는지 스스로도 설명할 수 없었습니다.
그 이후로 "AI와 인간의 경계선"을 진지하게 그었습니다. 3층 모델을 사용하고 있었는데, 3층으로는 입도가 너무 거칠어서 Logic 계층에 모든 책임이 떠넘겨져 있었던 것이 원인이었습니다. 그래서 6단계로 다시 나누었더니, 어느 단계를 누가 봐야 하는지가 마침내 보이기 시작했습니다.
이 기사는 그 6단계에 관한 이야기입니다.
3층 모델과는 다른 관점
저는 이전에 "리뷰의 3층 모델"이라는 기사를 쓴 적이 있습니다. 자동 게이트 (Automatic Gate), AI 리뷰, 인간 리뷰의 3층으로 분업하는 설계에 관한 이야기입니다.
그 기사는 "누가 무엇을 보는가"라는 큰 구조의 설계였습니다. 이번 6단계는 다른 관점입니다. **"AI와 인간의 경계선은 어디서 끊어지는가"**를 한 단계 더 세밀하게 해상도를 높여 보기 위한 정리입니다.
3층 모델은 설계도, 6단계는 설계도에 기입된 치수라는 이미지로 읽어주세요.
6단계의 정의
제가 현장에서 사용하고 있는 6단계는 다음과 같습니다. AI 비율은 실무 감각상의 기준으로, 팀이나 언어에 따라 달라집니다.
| 단계 | 대상 | AI 비율 | 인간 비율 | 주요 도구 |
|---|---|---|---|---|
| 1 | Format | 100% | 0% | pre-commit hook, Prettier |
| ... | ... | ... | ... | ... |
아래로 내려갈수록 "정답이 일의적이지 않은" 문제가 됩니다. Format에는 정답이 있지만, Architecture에는 정답이 없습니다. AI가 내려가는 것이 아니라, 문제의 성질이 변해가는 것이라고 파악하면 정리하기 쉽습니다.
단계 1: Format (100% AI)
들여쓰기 (Indent), 공백, 개행 코드, 문장 끝 세미콜론. 이것들은 pre-commit hook을 통해 전부 AI가 처리합니다.
#!/bin/bash
npx prettier --check . --ignore-unknown
여기에 인간의 판단은 1mm도 필요하지 않습니다. 리뷰어가 "들여쓰기가 맞지 않는다"라고 코멘트하는 것을 보면, 저는 마음속으로 사과하며 도구 도입을 제안합니다. 본인은 품질을 지키고 있다고 생각하겠지만, 소모되고 있는 것은 리뷰어 본인입니다.
단계 2: Lint (100% AI)
사용되지 않는 변수, 도달 불가능한 코드 (Unreachable Code), 암시적 형 변환 (Implicit Type Conversion). 정적 분석 도구가 찾아줍니다. ESLint, Ruff, mypy, tsc.
Format과 Lint는 같은 계층이 아닌가? 라고 생각할 수도 있습니다. 저는 나누고 있습니다. Format은 "외관"에 관한 규약이고, Lint는 "의미"에 관한 규약입니다. Format은 깨져도 동작하지만, Lint는 깨지면 동작하지 않습니다 (또는 향후 동작하지 않게 됩니다). 섞어버리면 pre-commit이 느려졌을 때 "어느 쪽을 제외할지" 판단할 수 없게 됩니다.
여기까지가 "PR(Pull Request)에조차 도달시키지 않는 계층"입니다. 저는 이 2단계만으로 매주 30분의 지적 시간을 구조적으로 제로로 만들었습니다.
단계 3: Style (90% AI / 10% 인간)
명명 (Naming), 함수의 분할 입도, 주석의 과부족, 가독성 (Readability).
여기서부터 AI 비율이 낮아집니다. CodeRabbit과 Copilot이 잘하는 영역이지만, 완전히 자동화할 수 없는 이유가 있습니다.
예를 들어 "함수명을 getUserData에서 fetchUser로 바꿔야 하는가"는 코드베이스 전체의 명명 규칙을 보지 않으면 판단할 수 없습니다. CodeRabbit은 .coderabbit.yaml을 통해 프로젝트 고유의 규칙을 읽어올 수 있지만, 모든 방침을 규칙화할 수는 없습니다.
저희 팀에서는 Style의 최종 승인은 인간이 합니다. AI가 90%의 지적을 내놓고, 인간이 "이 제안은 채택, 이것은 기각"이라고 판단합니다. "재밌게 가보자"라고 마음속으로 외치며, 기각할 때의 이유를 한 줄 코멘트로 남겨두면 다음 AI 리뷰의 정밀도가 올라갑니다.
단계 4: Logic (AI 60% / 인간 40%)
이곳이 제가 3개의 버그를 통과시킨 지점입니다.
N+1 문제, SQL 인젝션 (SQL Injection), 처리되지 않은 예외, 명백한 에지 케이스 (Edge Case). AI는 이 정도까지는 찾아내 줍니다. Macroscope의 벤치마크 (Benchmark)에 따르면, 버그 탐지 정밀도는 Macroscope 48%, CodeRabbit 46%, Cursor BugBot 42%, Greptile 24%입니다. 절반 이상은 놓친다고 생각하는 것이 안전합니다.
CodeRabbit과 Copilot을 비교한 벤치마크에서는 CodeRabbit이 F1 51.5% / 재현율 (Recall) 52.5%, Copilot이 F1 44.5% / 재현율 (Recall) 36.7%를 기록했습니다. CodeRabbit이 더 잘 찾아내기는 하지만, 그럼에도 재현율 (Recall)은 절반을 조금 넘는 수준입니다. "6할 정도만 찾아내도 훌륭하다"는 것이 현재의 체감에 가깝습니다.
제가 통과시킨 3개의 버그는 전부 "비즈니스 로직 (Business Logic) 유래의 에지 케이스 (Edge Case)"였습니다.
- "빈 배열이 오면 처리를 스킵한다"가 사양 (Specification)이었음에도, AI는 "빈 배열이라도 처리한다"는 코드를 문제없다고 판정
- 외부 API의 재시도 (Retry) 조건이 "429만 해당"하는 것이 사양이었음에도, AI는 "5xx 전체를 재시도"하도록 제안
- 페이지네이션 (Pagination) 경계에서 1건이 어긋나는 고전적인 버그를, AI는 "테스트가 통과했으니 OK"라고 판정
이것들은 AI의 관점에서 보면 코드로서 올바릅니다. 사양서 (Specification)를 보지 않는 AI는 코드베이스 (Codebase) 내의 정합성만을 볼 뿐입니다.
Claude Code의 /review나 /ultra review는 여러 에이전트 (Agent)가 각도를 달리하여 살펴보기 때문에, 단일 AI 리뷰보다는 놓치는 부분이 줄어듭니다. 그럼에도 사양 판단의 최종 책임은 인간에게 있습니다. Claude Code 공식 문서 (Official Documentation)에서도 로직 에러 (Logic errors)나 에지 케이스 (Edge cases)는 "전체 코드베이스의 컨텍스트 (Context of your full codebase)" 내에서 탐지된다고 적혀 있으며, 사양서는 탐지 범위 밖에 있습니다.
제가 현장에서 운용하고 있는 규칙은 심플합니다. 로직 (Logic) 계층에서 AI가 지적한 부분은 AI에게 맡기고, AI가 지적하지 않은 부분이야말로 인간이 면밀히 살펴본다. AI의 코멘트 수가 많은 PR (Pull Request)일수록 인간의 리뷰는 짧게 끝납니다. 반대로 AI의 코멘트가 제로인 PR이야말로 사양서를 펼쳐 30분 동안 읽어볼 가치가 있습니다. 역설적이지만, 이것이 버그를 통과시키지 않게 된 가장 큰 운영상의 변화였습니다.
단계 5: Design (AI 30% / 인간 70%)
책임 분할, API 경계, 의존 관계 (Dependency)의 방향.
여기서부터는 AI가 나설 자리가 급격히 줄어듭니다. "이 메서드 (Method)를 User 클래스에 둘 것인가, 별도의 Service 클래스에 둘 것인가"는 코드베이스의 설계 사상에 달려 있습니다. AI는 기존 패턴을 학습하기는 하지만, "이 패턴을 늘려야 하는가, 줄여야 하는가"라는 방향성의 판단은 할 수 없습니다.
제가 디자인 (Design) 계층에서 AI에게 기대하는 것은 기껏해야 "이 함수는 150줄입니다. 분할을 검토해 주세요"와 같은 기계적인 힌트뿐입니다. 나머지 70%는 인간이 페어 리뷰 (Pair Review)를 통해 판단합니다.
여기서 효과적인 것은 2인 리뷰입니다. 1명일 때는 "자신의 취향"을 "설계 판단"으로 착각하기 쉽습니다. 2명이 있으면 "이건 어느 설계로도 동작하네, 그럼 기존 패턴에 맞추자"와 같은 대화가 가능합니다. 마치 '신장의 야망'에서 군의 (軍議)를 하는 것과 같습니다. 성을 지킬지 공격할지는 군의를 통해 결정됩니다.
디자인 (Design) 계층에서 제가 AI를 신뢰하지 않는 또 다른 이유가 있습니다. AI는 학습 데이터 속의 "평균적인 좋은 설계"로 치우치는 경향이 있으며, 해당 코드베이스 고유의 제약 사항을 읽지 않습니다. 예를 들어 "멀티 테넌트 (Multi-tenant) DB이므로 Service 계층은 반드시 tenant_id를 인자로 받아야 한다"라는 로컬 규칙은 AI에게 전달되기 어렵습니다. 경로 기반 지침 (Path-scoped instructions)으로 노력하면 전달할 수 있겠지만, 규칙이 늘어날수록 유지보수 비용도 상승합니다. 설계의 방향성은 코드에 앞서 존재하는 암묵적인 팀의 합의로 결정되기에, 문서화되지 않은 것을 AI에게 읽히는 것은 원리적으로 어렵다고 저는 생각합니다.
단계 6: Architecture (AI 0% / 인간 100%)
시스템 경계, 데이터 흐름 (Data Flow), 인증 (Authentication)의 책임 범위, 배포 단위.
여기에 AI는 전혀 포함되어 있지 않습니다. 이유는 단순합니다. **아키텍처(Architecture) 판단은 '정답'이 아니라 '미래 예측'**이기 때문입니다. 3년 후에 이 시스템이 어떻게 성장할지, 팀이 어떻게 확장될지, 비즈니스가 어디로 피보트(Pivot)할지. 이러한 질문들에 대해 AI는 그럴듯한 답은 내놓을 수 있지만, 책임을 질 수는 없습니다.
GitHub Copilot의 문서에서도 'missing most architectural concerns(대부분의 아키텍처 관련 고려 사항을 놓침)'라고 공식적으로 명시하고 있습니다. AI 리뷰는 아키텍처 판단을 지원하지 않습니다.
아키텍처(Architecture) 리뷰는 리뷰라기보다 '설계 회의'입니다. PR(Pull Request)에 대한 작업이 아니라, PR 이전에 해야 할 작업입니다. ADR(Architecture Decision Record)을 작성하고, 테크 리드(Tech Lead)가 퍼실리테이트(Facilitate)하여 30분간 논의합니다. 코드를 쓰기 전에 방향이 결정되어 있지 않다면, PR 리뷰 단계에서 논쟁이 벌어져도 이미 늦다는 것이 저의 교훈입니다.
구체적인 예로, "인증 로직(Authentication Logic)을 각 마이크로서비스(Microservice)에 둘 것인가, API 게이트웨이(API Gateway)에 집약할 것인가"와 같은 결정은 PR에서 논쟁이 되면 지옥이 됩니다. 코드를 다 작성한 후에 결정하면 한쪽을 버려야 하게 됩니다. 사전에 ADR을 통해 "집약한다"라고 결정해 두면, PR 리뷰에서는 "ADR과 일치하는가"만 확인하면 끝납니다. AI는 ADR과 일치하는지를 기계적으로 체크할 수 있으므로, ADR을 작성하는 순간 Stage 6의 일부가 Stage 5나 Stage 4로 내려오는 흥미로운 현상도 일어납니다. 문서화함으로써 AI 비율이 높아지는 것입니다.
6단계로 나누면 「Approve의 의미」가 변한다
3층 모델일 때의 Approve는 "포맷(Format) OK, AI OK, 나도 대략 확인했음"이라는 3종 세트였습니다.
6단계로 운영하기 시작한 이후, 저는 Approve를 누를 때 스스로에게 질문합니다.
"나는 어느 단계까지 책임을 지고 이 Approve를 누르고 있는가?"
Format과 Lint는 통과했다. Style은 AI의 지적에 동의했다. Logic은 사양서(Specification)와 대조하여 3가지 에지 케이스(Edge Case)를 확인했다. Design은 책임 분할(Responsibility Segregation)에 위화감이 없다. Architecture는 사전 설계 회의에서 논의를 마쳤다.
이 체크를 통과한 Approve는 3층 모델일 때의 Approve보다 무게감이 있습니다. 반대로 Logic과 Design에 불안함이 있다면, "Approve 하지 않는 선택"을 하기 쉬워집니다. "일단 LGTM(Looks Good To Me)"이 나오기 어려운 구조입니다.
팀 도입 단계
갑자기 6단계를 전부 도입하려고 하면 아마 좌절할 것입니다. 제 경험상 다음과 같은 순서가 현실적입니다.
- 먼저 Stage 1-2를 hooks로 고정하기: 여기는 하루면 끝납니다. 즉시 효과가 나타납니다.
- Stage 3에 CodeRabbit 또는 Copilot 도입하기: Copilot 계약이 있다면 무료입니다. 1주일 정도 익숙해지게 합니다.
- Stage 4를 위한 사양서(Specification) 정비: 여기가 가장 시간이 많이 걸립니다. AI가 볼 수 없는 "사양 유래의 에지 케이스(Edge Case)"를 먼저 인간이 명문화해야 합니다.
- Stage 5-6는 팀 문화로 키우기: 페어 리뷰(Pair Review)와 ADR. 시스템화보다는 습관화가 중요합니다.
Stage 4에서 막힌다면, 저처럼 운영 환경에서 버그를 3개 정도 통과시키는 경험을 할 수 있습니다. 농담이 아니라, 구조적으로 "AI가 볼 수 있는 범위"와 "인간이 봐야 할 범위"를 나누지 않으면 Logic 계층은 AI에게 맡겨지게 됩니다.
「AI에게 맡겨서 안심」이 가장 위험하다
제가 버그를 3개 통과시킨 진짜 이유는 AI 리뷰가 완벽하다고 믿었기 때문이 아닙니다. "AI가 보고 있으니, 나는 안 봐도 된다"라고 무의식적으로 판단했기 때문입니다.
이는 인지적 지름길(Cognitive Shortcut)이며, AI 리뷰를 도입하는 모든 팀에서 발생합니다. Stage 4의 Logic 계층이 가장 위험한 이유는 AI의 커버리지(Coverage)가 60%라는 "어중간한 높이"이기 때문입니다. 0%라면 인간이 전부 보고, 100%라면 AI에게 맡깁니다. 60%는 "7할 정도는 괜찮겠지"라는 방심을 낳습니다.
6단계로 나눈 가장 큰 효용은 Stage 4가 "중간 존(Intermediate Zone)"이라는 것을 가시화했다는 점입니다. 중간 존은 인간의 집중력이 가장 많이 필요한 곳이라는 사실을 알게 되었습니다.
요약
요약
- 코드 리뷰는 Format / Lint / Style / Logic / Design / Architecture의 6단계로 나눌 수 있다
- AI 비율은 Format 100%에서 Architecture 0%로 단계적으로 낮아진다
- 가장 위험한 곳은 Stage 4인 Logic 계층이다. AI 커버리지 60%가 방심을 불러일으킨다
- Approve를 누르기 전에 "어느 단계까지 책임을 지고 있는가"를 스스로에게 질문해야 한다
- Stage 1-2부터 도입하고, Stage 4를 위한 사양서(Specification) 정비에 가장 많은 시간을 투자해야 한다
3층 모델이 "누가 무엇을 보는가"에 대한 설계도라면, 6단계는 "어디에 집중력을 남길 것인가"에 대한 해상도입니다. AI 리뷰가 당연해진 지금, 경계선을 어디에 그을지는 각 팀이 스스로 결정해야 할 문제라고 생각합니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Zenn AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기