
AI가 작성한 코드는 누가 리뷰하는가 ─ 하루 만에 7건의 지적을 받으며 다져진 개인 개발 체제
요약
1인 개발자가 Claude Code로 코드를 구현하고 CodeRabbit으로 리뷰하는 '쓰는 AI와 보는 AI를 나누는' 개발 체제를 소개합니다. 동일한 AI가 작성과 리뷰를 동시에 할 때 발생하는 편향성을 극복하고, 자동화 과정에서 발생할 수 있는 잠재적 장애를 리뷰 AI가 어떻게 잡아내는지 실례를 통해 보여줍니다.
핵심 포인트
- 작성 AI와 리뷰 AI를 분리하여 관점의 독립성 확보
- CodeRabbit을 통한 자동 PR 리뷰로 개인 개발의 품질 관리
- 동작 여부를 넘어 OpenAPI 중복, 설정값 유연성 등 세부 결함 포착
- 배포 자동화 시 발생할 수 있는 페일 세이프(fail-safe) 로직의 중요성
서론
AI에게 코드를 작성하게 하고 있는 개인 개발자분들에게 묻고 싶은 것이 있습니다.
그 코드, 누가 리뷰하고 있습니까?
저는 개인 개발로 뉴스 큐레이션 서비스(DevPick / AgentPick)를 운영하고 있으며, 구현은 거의 Claude Code에 맡기고 있습니다. 1인 개발이라 리뷰어가 없습니다. 그렇다고 해서 "AI가 작성한 것을 내가 모든 행을 리뷰한다"는 방식은 솔직히 지속하기 어렵습니다.
그래서 제가 채택하고 있는 것이, 구현은 Claude Code, 리뷰는 CodeRabbit이라는 "쓰는 AI와 보는 AI를 나누는" 체제입니다.
이 기사는 그 체제가 본령을 발휘한(즉, 구현 AI가 하루 만에 7건의 지적을 받은) 어느 일요일의 실록과, 최종적으로 리뷰를 시스템으로 강제하기까지의 이야기입니다.
왜 AI를 나누는가
이유는 간단합니다. 같은 AI가 쓰고 리뷰하면, 같은 편견과 함께 그대로 통과시켜 버리기 때문입니다.
인간의 셀프 리뷰와 같은 구조입니다. 작성 직후의 자신은 "동작하는 것을 확인했다"는 만족감 속에 있기 때문에, 자신의 전제를 의심할 수 없습니다. 이는 모델의 똑똑함 문제가 아니라, 관점의 독립성 문제입니다.
CodeRabbit은 PR을 열면 자동으로 리뷰가 실행되며, 행 단위의 지적과 워크스루(walkthrough)가 제공됩니다. 구현한 쪽(Claude Code)은 그 지적에 대해 타당하다면 반영하고, 전제가 다르다면 근거를 제시합니다. 개인 개발에서도 팀 개발의 리뷰 프로세스가 그대로 돌아갑니다.
어느 일요일의 실록
그 체제로 운용하던 일요일, 마침 운영 계통의 태스크가 집중되었습니다. 시계열로 살펴보겠습니다.
아침: 외형 모니터링을 넣었더니 갑자기 버그가 발견되다
UptimeRobot으로 헬스 체크(health check) 외형 모니터링을 설정했더니, 모니터가 즉시 Down 판정을 내렸습니다. 사이트는 정상적으로 보입니다.
원인은 UptimeRobot이 생사 확인에 HEAD 요청을 사용하는 반면, FastAPI는 @router.get만으로는 HEAD를 받지 못해(405를 반환) 발생하는 문제였습니다. 모니터링을 넣은 순간, 모니터링 측과의 호환성 버그가 발견된 형태입니다.
Claude Code가 수정 PR을 만들고 테스트도 통과하여 "검증 완료" 상태로 만들었습니다. 그런데 거기에 CodeRabbit으로부터 2건의 지적이 들어왔습니다.
methods=["GET", "HEAD"]와 같은 1개의 라우트 정의는 OpenAPI의 operation ID가 중복된다 (실제로 FastAPI가 경고를 내고 있었다)- 테스트의 "25시간 전이라면 stale"라는 고정값은 설정값을 바꾸면 깨진다
둘 다 "동작함"을 확인한 뒤에 남는 종류의 결함입니다.
점심: 자동 배포를 만들었더니, 지적이 진짜 장애를 막다
이어서 GitHub Actions를 통한 자동 배포(main 머지 → VPS 반영)를 구축했습니다. 여기서도 CodeRabbit으로부터 2건의 지적이 있었습니다.
- PR 라벨 취득 API가 실패했을 때
|| echo ""로 "라벨 없음"이라고 해석하고 있다. 이는 스킵 지정을 무시하고 배포를 강행하게 된다 - SSH로 받는 run ID의 검증이
^[0-9]*$로 되어 있어, 빈 문자열을 허용하고 있다
첫 번째 지적대로 페일 세이프(fail-safe, 라벨을 확인할 수 없으면 배포하지 않고 실패)하도록 고쳤더니——머지 후 1시간도 채 되지 않아, 첫 자동 배포에서 바로 그 API가 403을 반환했습니다(GITHUB_TOKEN 권한 부족). 지적을 통해 넣어둔 안전장치가, 넣자마자 실제 에러로 발동한 것입니다. 오배포가 아니라 작업(job) 실패로 현상화되었기에 권한을 수정하는 것으로 끝낼 수 있었습니다.
저녁: 자동화가 모니터링을 망가뜨리고, 리뷰가 "검증 완료"의 허점을 찌르다
저녁, 다시 UptimeRobot이 Down 통지를 보냈습니다. 사이트는 정상입니다. 이번 원인은 자동 배포 그 자체였습니다.
기사 페치는 APScheduler의 6시간 간격 작업(job)인데, **interval 작업의 첫 실행은 "기동 후 6시간 뒤"**입니다. 배포할 때마다 재기동 → 타이머 리셋이 반복된 결과, 페치가 13시간 동안 실행되지 않았고, 헬스 체크의 신선도 판정(12시간)을 초과했습니다.
수정 방법은 기동 직후에 첫 실행을 예약하는 것입니다. Claude Code는 로컬에서 "재기동 → 즉시 페치가 실행됨"을 실제로 확인하고 PR을 냈습니다. 이번에야말로 검증 완료——라고 생각했으나, CodeRabbit으로부터 지적이 왔습니다.
misfire_grace_time을 명시하십시오. 기본 유예 시간은 1초이므로, 기동 직후의 실행은 지연으로 인해 놓칠 가능성이 있습니다.
즉 "테스트와 로컬 검증에서는 항상 작동하지만, 운영 환경의 악조건에서만 조용히 죽는" 허점이 남아 있었다. 구현한 쪽이 동작 확인에 성공한 직후일수록, 그 주변을 의심하지 않게 된다. 이날 가장 뼈아픈 지적이었습니다.
밤: "고빈도로 버그를 심는 너로서는 어떻게 생각해?"
하루의 끝에 구현 AI에게 물어보았습니다. "CR(Code Review) 지적이 꽤 많네. 고빈도로 버그를 심는 너로서는 어떻게 생각해?"
돌아온 분석이 흥미로워 공유합니다. 7건의 지적은 전부 "작동하지 않는 버그"가 아니라, 정상계 (Normal Case)를 검증하고 만족한 뒤에 남는 종류의 결함이며, 패턴화할 수 있다는 것입니다.
| 결함 클래스 | 이날의 실례 |
|---|---|
| 외부 호출 실패 시 fail-open 상태가 됨 | API 실패 → "라벨 없음" → 배포 강행 |
| ... | ^[0-9]*$ 가 빈 문자열을 통과함 |
| ID·이름 충돌 | OpenAPI operation ID 중복 |
| 테스트가 설정값과 독립적이지 않음 | stale 임계값 25시간 고정 |
역으로 말하면, 리뷰 AI는 이 클래스의 결함을 매번 같은 각도에서 찔러줍니다. 쓰는 AI와 보는 AI의 분업이 기능하는 이유가 바로 여기에 있습니다.
구조로 강제하기: hooks로 PR 생성 차단
다만, 리뷰망이 있다고 해서 무책임하게 던지면, 지적 → 수정 → 재 CI의 왕복으로 대기 시간만 늘어날 뿐입니다. 던지기 전의 셀프 체크는 역시 필요하며, 게다가 AI의 "주의하겠습니다"는 인간과 마찬가지로 믿을 수 없습니다.
그래서 Claude Code의 hooks를 사용하여, 셀프 리뷰를 실시하지 않은 PR 생성을 기계적으로 차단했습니다. .claude/settings.local.json에 PreToolUse 훅을 심습니다.
{
"hooks": {
"PreToolUse": [
...
동작 방식은 다음과 같습니다.
- Claude Code가
gh pr create를 실행하려고 함 - 훅이
.git/claude-reviewed마커와 현재의 HEAD를 대조 - 불일치(즉, 이 HEAD는 리뷰 미실시 상태)라면 명령 실행 전에 차단하고, "/code-review low 로 리뷰한 뒤에"라는 지시를 Claude Code에 반환
- 리뷰와 지적 대응을 마치고 마커를 작성하면, PR 생성이 통과됨
포인트는 이것이 AI의 기억이나 프롬프트가 아니라 하네스 (Harness) 측의 강제라는 점입니다. hooks는 Claude Code 본체가 결정론적으로 실행하므로, AI가 잊어버리거나 태만하게 굴어도 발동합니다. "에이전트에게 부탁하기"를 "환경의 제약"으로 변환하는 이미지입니다.
이로써 다층 방어가 갖춰졌습니다.
| 층 | 담당 | 역할 |
|---|---|---|
| 구현 | Claude Code | 작성 · 테스트 · 로컬 검증 |
| ... |
회고: 4가지 배움
1. 리뷰의 가치는 똑똑함이 아니라 독립성에 있다
같은 모델이라도, 작성한 문맥을 가지지 않은 별도의 인스턴스라면 가치가 있습니다. 다만, 다른 벤더의 리뷰 특화 도구는 관점의 차이가 더 잘 드러난다는 것이 체감입니다.
2. AI의 결함은 패턴화할 수 있다
"정상계 검증 후에 남는 종류"에 편중되므로, fail-open · 기본값 · 경계 입력 · ID 충돌 등을 자문 리스트로 만들면, 던지기 전에 해결할 수 있는 비율이 높아집니다.
3. 지적은 의외로 금방 실전에서 드러난다
페일 세이프 (Fail-safe)에 대한 지적이 1시간도 채 되지 않아 실제 403 에러로 발동했던 것처럼, "이론상의 지적"이라고 얕봐서는 안 됩니다.
4. AI에 대한 개선 요구는 구조로 변환한다
"주의해"는 AI에게도 통하지 않습니다. hooks와 같은 결정론적인 강제로 바꿀 수 있는 것은 바꿉니다.
현재 상태
이 체제로 Issue 생성 → 구현 → 리뷰 → 머지(Merge) → 자동 배포 → 모니터링까지 1인 + AI 2대로 돌아가고 있습니다. 이날 하루 동안 해결한 Issue는 4건, 머지한 PR은 5개였습니다.
AgentPick은 Claude · AI 개발 효율화 뉴스를 매일 수집하여 요약합니다. 이 기사와 같은 개발 스타일에 관심이 있는 분들에게는 딱 맞는 정보원이 될 것입니다. 무료이니 꼭 확인해 보세요.
Discussion

AI 자동 생성 콘텐츠
본 콘텐츠는 Zenn AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기