---
title: "AI 코드 리뷰, 어렵지 않게 운영하는 법"
subtitle: "Claude Code와 Codex를 함께 쓰는 사람을 위한 설명"
date: 2026-08-25
document_type: "설명용 가이드"
companion: "ai-code-review-pilot-playbook.md"
---

## 문서의 목적

AI 코드 리뷰 파일럿 운영안을 기술적인 규칙집이 아니라 사람이 편하게 읽고 이해할 수 있는 말로 풀어쓴다. 이 문서로 전체 원리를 이해한 뒤, 실제 작업할 때만 실행용 플레이북의 프롬프트와 기록 양식을 사용하면 된다.

## 먼저 결론부터

AI에게 코드를 맡길 때 가장 위험한 방식은 이런 것이다.

> 코드를 만들게 한다 → 스스로 검토하게 한다 → 스스로 고치게 한다 → 문제가 없다고 할 때까지 반복한다.

겉으로는 꼼꼼해 보이지만, 실제로는 AI가 잘못 짚은 문제까지 계속 고치면서 코드를 불필요하게 복잡하게 만들 수 있다. 처음에 내린 잘못된 판단이 다음 수정의 근거가 되고, 그 수정이 다시 새로운 지적을 만드는 식으로 일이 커질 수 있다.

그래서 앞으로는 역할을 나눈다.

- AI 리뷰어는 문제를 찾고 설명만 한다.
- 사람은 그 지적이 맞는지 확인하고 고칠 것을 선택한다.
- 수정자는 사람이 선택한 것만 고친다.
- 수정 후에는 테스트하고, 위험한 변경만 다시 검토한다.

핵심은 AI를 덜 쓰는 것이 아니다. **AI가 찾는 일과 고치는 일을 자동으로 연결하지 않는 것**이다.

## 왜 AI 리뷰를 두 번 하는가

같은 코드를 같은 AI에게 보여줘도 매번 똑같은 답이 나오지 않는다. 첫 번째에는 놓친 문제를 두 번째에는 발견할 수 있고, 반대로 첫 번째에 맞게 지적한 것을 두 번째에는 말하지 않을 수도 있다.

그래서 일반적인 코드 변경은 Claude와 Codex에게 한 번씩 독립적으로 보여주는 것으로 시작한다. 두 AI가 서로의 답을 먼저 보게 하지 않는다. 한쪽의 의견을 먼저 보여주면 다른 AI가 그 의견을 따라갈 수 있기 때문이다.

다만 두 AI가 같은 말을 했다고 그 지적이 자동으로 정답이 되는 것은 아니다. 두 AI 모두 같은 파일만 보고 같은 정보를 놓쳤다면 똑같은 오답을 낼 수 있다.

따라서 중요한 것은 몇 명이 동의했느냐가 아니라 다음이다.

- 실제 코드의 어느 부분이 근거인가
- 그 상태가 프로그램에서 정말 발생할 수 있는가
- 문제가 생기면 어떤 영향이 있는가
- 테스트나 실행으로 확인할 수 있는가

## 리뷰 전에 먼저 알려줘야 할 것

AI는 코드만 보고 개발자의 의도를 완벽하게 알아낼 수 없다. 코드에는 현재 구현이 들어 있지만, 왜 이렇게 만들었는지는 충분히 드러나지 않을 수 있다.

리뷰를 맡기기 전에 다음 정도는 알려주는 것이 좋다.

- 이번에 무엇을 만들거나 고쳤는지
- PRD나 DESIGN 중 어떤 문서가 기준인지
- 어디까지 수정해도 되는지
- 기존 함수 이름이나 API를 바꿔도 되는지
- 테스트를 바꿀 수 있는 작업인지

예를 들어 기존 API와의 호환성을 유지해야 하는 작업인데 이 사실을 알려주지 않으면, AI는 함수 구조를 더 깔끔하게 만든다며 외부에서 사용 중인 이름이나 반환값을 바꾸자고 할 수 있다. 코드만 보면 좋은 개선이지만 프로젝트 전체에서는 장애가 될 수 있다.

## 테스트는 리뷰 전에 한 번 돌려본다

AI 리뷰 전에 테스트·타입체크·린트를 실행한다. 반드시 모두 통과시킨 다음 리뷰하라는 뜻은 아니다. 현재 상태를 기록해 두자는 뜻이다.

그래야 리뷰와 수정이 끝난 뒤 발생한 실패가 원래 있던 것인지, 이번 수정 때문에 생긴 것인지 구분할 수 있다.

테스트가 실패한 상태에서도 AI에게 원인을 찾아달라고 할 수 있다. 다만 작업을 끝낼 때는 프로젝트에서 필수로 정한 검사를 통과해야 한다.

## AI에게 저장소를 보여준다는 뜻

리뷰할 파일 하나만 던져주면 AI는 그 파일 안에서만 문제를 추측한다. 하지만 실제 오류 여부는 다른 파일에서 결정되는 경우가 많다.

예를 들어 어떤 함수만 보면 빈 값이 들어올 가능성이 있어 보이지만, 실제 호출자는 항상 값을 먼저 채운 다음 함수를 호출할 수 있다. 이 경우 해당 파일만 본 AI는 존재하지 않는 상황을 버그라고 지적할 수 있다.

그래서 AI가 필요할 때 다음을 찾아볼 수 있도록 저장소 탐색 권한을 준다.

- 이 함수를 실제로 부르는 코드
- 데이터가 만들어지고 변하는 과정
- 설정과 환경변수
- 테스트와 문서
- 비동기 처리와 오류 처리 경로

저장소 전체를 한꺼번에 프롬프트에 붙여 넣으라는 뜻은 아니다. AI가 필요한 파일을 직접 검색하고 근거를 확인할 수 있게 하라는 뜻이다.

## AI가 지적한 것은 아직 결함이 아니다

AI가 “버그입니다”라고 말해도 그 순간 결함으로 확정하지 않는다. 우선 두 종류로 나눈다.

### 근거가 있는 결함 후보

파일 위치와 발생 조건이 분명하고, 실제 호출 과정이나 테스트로 확인할 수 있는 지적이다.

### 확인이 더 필요한 항목

가능성은 있지만 AI가 실제로 확인하지 못한 내용이다. 이것을 `verify`라고 부른다.

예를 들어 AI가 “동시에 두 요청이 들어오면 값이 꼬일 수 있다”고 했지만 실제 실행 구조가 단일 스레드인지 확인하지 못했다면 아직 결함이 아니다. 사람이 코드 검색이나 테스트로 확인해야 한다.

`verify`를 그대로 수정자에게 넘기면 안 된다. 확인되지 않은 가능성을 실제 문제처럼 고치기 시작할 수 있기 때문이다. 먼저 사람이 확인해서 다음 중 하나로 바꾼다.

- 실제 문제로 확인됨
- 문제가 아님

특히 보안·결제·데이터 삭제처럼 위험한 영역의 `verify`가 남아 있다면 작업을 끝내지 않는다.

## 사람은 무엇을 결정하는가

확인된 결함 후보는 사람이 세 가지로 나눈다.

- `accept`: 이번 작업에서 고친다.
- `decline`: 오탐이거나 원래 의도된 동작이므로 고치지 않는다.
- `defer`: 실제 문제지만 이번 작업 범위 밖이므로 나중에 처리한다.

defer라고 해서 모두 백로그에 넣을 필요는 없다. 영향이 작고 재현도 되지 않는 항목을 계속 쌓으면 중요한 문제가 사소한 항목 속에 묻힌다. 실제 영향과 근거가 있는 문제만 남긴다.

## 수정자는 선택된 것만 고친다

수정자에게는 accept 목록만 전달한다. “주변 코드도 같이 개선해 주세요” 같은 열린 지시를 추가하지 않는다.

AI가 수정하는 동안 새로운 문제를 발견할 수는 있다. 그 경우 마음대로 함께 고치지 말고 별도로 보고하게 한다. 새 문제도 다시 사람의 판단을 거쳐야 한다.

테스트는 원칙적으로 읽을 수 있게 하되 마음대로 고치지는 못하게 한다. 수정한 코드에 맞춰 테스트까지 바꾸면, 코드가 잘못됐는데도 테스트를 느슨하게 만들어 통과시킬 수 있기 때문이다.

물론 요구사항이 바뀌었거나 테스트 자체가 틀렸다면 테스트 변경이 필요하다. 이때는 코드 수정과 섞지 않고, 왜 테스트를 바꿔야 하는지 먼저 확인한 뒤 별도 작업으로 처리한다.

## 테스트가 실패했다고 항상 코드가 틀린 것은 아니다

테스트 실패는 중요한 신호지만 무조건 정답은 아니다. 실제 서비스에서는 발생할 수 없는 상태를 단위 테스트가 억지로 만들어 검사할 수도 있다.

그래서 수정 후 특정 테스트가 깨졌다면 먼저 이렇게 묻는다.

> 이 테스트가 검사하는 상태가 실제 프로그램에서도 발생할 수 있는가?

실제로 발생 가능한 상태라면 코드를 고쳐야 한다. 발생할 수 없는 상태라면 테스트가 내부 구현을 지나치게 고정했는지 확인해야 한다.

중요한 것은 테스트를 무시하는 것이 아니라, **테스트가 무엇을 보증하는지 이해하고 사용하는 것**이다.

## 언제 다시 리뷰하는가

몇 줄을 수정했는지만 보고 재리뷰 여부를 결정하지 않는다.

로그인 권한을 결정하는 조건 한 줄은 수정량이 매우 작아도 위험하다. 반대로 자동 포맷팅으로 파일 절반이 바뀌어도 프로그램 동작은 같을 수 있다.

따라서 수정량보다 다음을 본다.

- 잘못되면 피해가 큰가
- 여러 파일이나 서비스에 영향을 주는가
- 외부에서 사용하는 API가 바뀌는가
- 데이터나 권한을 다루는가
- 원래 코드와 다른 동작이 새로 생겼는가

작고 단순한 수정은 테스트 통과 후 끝낼 수 있다. 일반적인 수정은 변경 부분만 한 번 더 볼 수 있다. 보안·결제·데이터·동시성처럼 위험한 수정은 Claude와 Codex 모두에게 다시 검토시킨다.

여기서도 자동 반복은 하지 않는다. 새 지적이 나오면 다시 사람이 확인하고, 고칠 항목을 선택한 뒤 수정한다.

## 카나리는 왜 필요한가

AI가 저장소를 실제로 읽지 못해도 그럴듯한 리뷰 결과를 만들 수 있다. 따라서 답변이 길고 자연스럽다는 것만으로는 파일 접근이 정상이라는 사실을 알 수 없다.

그래서 리뷰를 시작할 때 읽을 수 있는 위치에 임의의 문자열이 담긴 파일을 하나 만들어 둔다. AI에게 파일 경로만 알려주고 내용을 읽어 답하게 한다. 문자열 자체는 프롬프트에 쓰지 않는다.

AI가 값을 정확히 읽으면 최소한 그 경로에 실제로 접근했다는 것을 확인할 수 있다. 읽지 못하면 그 리뷰는 진행하지 않는다.

이 확인을 첫 번째 리뷰 요청에 같이 넣으면 별도의 AI 호출은 필요하지 않다. 다만 프롬프트와 처리 시간이 조금 늘어나는 비용까지 완전히 사라지는 것은 아니다.

카나리에는 실제 비밀번호나 개인정보를 넣지 않는다. 의미 없는 임의 문자열만 사용한다.

## 변경의 위험도는 단순하게 나눈다

처음부터 정교한 점수표를 만들 필요는 없다.

### 저위험

주석, 문구, 포맷팅처럼 프로그램 동작이 거의 바뀌지 않는 작업이다. 정적 검사만 하거나 AI 한 번 정도면 충분할 수 있다.

### 일반

보통의 기능 추가나 국소적인 로직 수정이다. Claude와 Codex에 한 번씩 독립 리뷰를 맡기는 것으로 시작한다.

### 고위험

잘못되면 손실이 크거나 발견·복구가 어려운 변경이다. 다음과 같은 작업이 포함된다.

- 로그인·권한·개인정보
- 결제·정산·금액 계산
- 데이터 삭제·이전·DB 구조 변경
- 동시성·비동기·트랜잭션
- 외부 API와 여러 모듈에 걸친 변경
- 파일 업로드·명령 실행·사용자 입력 처리
- 배포 설정·시크릿·환경변수

고위험 작업은 Claude와 Codex에 각각 두 번씩 리뷰를 맡기는 것으로 시작한다. 이 숫자가 정답이라는 뜻은 아니다. 몇 달간 기록한 뒤 우리 프로젝트에 맞게 줄이거나 늘린다.

## 무엇을 기록해야 하는가

모든 대화를 보관할 필요는 없다. 다음 정도만 기록하면 된다.

- 변경이 저위험·일반·고위험 중 무엇이었는지
- Claude와 Codex를 각각 몇 번 사용했는지
- AI가 지적한 항목 중 실제 문제로 확인된 것이 몇 개인지
- 오탐과 확인 필요 항목이 얼마나 나왔는지
- 사람이 선별하는 데 시간이 얼마나 걸렸는지
- 리뷰에서 놓쳤다가 나중에 발견된 문제가 있었는지
- 카나리가 실패하거나 잘못 경고한 적이 있었는지

AI의 지적을 사람이 accept했다고 해서 실제 결함으로 계산하면 안 된다. 테스트·재현·실제 장애 등을 통해 문제가 맞다고 확인된 항목을 따로 세어야 한다.

3~6개월이 지나거나 일반 변경 약 20건, 고위험 변경 약 10건이 쌓이면 기록을 본다. 그때 비로소 일반 작업에 AI 두 개가 정말 필요한지, 고위험 작업에 네 번의 리뷰가 가치가 있었는지 판단한다.

## 실제 작업은 이렇게 흘러간다

예를 들어 로그인 만료 시간을 처리하는 코드를 수정했다고 하자. 인증과 관련됐으므로 고위험 작업으로 본다.

먼저 어떤 동작을 바꾸려는지와 기준 문서를 적고, 기존 테스트 결과를 기록한다. 그다음 Claude와 Codex가 서로의 답을 보지 않은 상태에서 각각 코드를 검토한다.

Claude가 “토큰 만료 시각 비교가 잘못됐다”고 지적했고, Codex가 “서버와 브라우저의 시간대가 다르면 문제가 생길 수 있다”고 지적했다고 하자. 두 의견이 다르다고 어느 한쪽이 틀린 것은 아니다. 반대로 둘이 같은 말을 했다고 맞는 것도 아니다.

사람은 실제 시간 저장 방식, 호출 경로, 테스트를 확인한다. Claude의 지적은 실제 오류로 확인됐지만 Codex의 지적은 모든 시각을 UTC로 저장하기 때문에 성립하지 않을 수 있다. 그러면 첫 항목은 accept, 두 번째는 decline으로 분류한다.

수정자는 accept된 첫 항목만 고친다. 테스트를 다시 실행하고, 인증 관련 고위험 변경이므로 두 모델에게 수정된 부분을 다시 검토시킨다. 남아 있는 고위험 `verify`가 없고 필수 검사가 통과하면 사람이 작업 종료를 선언한다.

이것이 전체 절차다. 복잡해 보이는 용어를 빼면 결국 다음과 같다.

> **두 AI에게 따로 물어보고, 사람이 사실을 확인하고, 확인된 것만 고친 다음, 위험한 변경만 다시 본다.**

## 너무 복잡하게 만들지 않기 위한 팁

- 처음부터 완벽한 자동화 시스템을 만들지 않는다.
- 일반 작업은 Claude 1회와 Codex 1회로 시작한다.
- AI가 작성한 리뷰를 다시 AI에게 계속 비평시키지 않는다.
- 스타일·이름·주석 리뷰는 결함 리뷰와 분리한다.
- 여섯 개 문서를 모두 읽으라고 하지 말고 이번 작업의 기준 문서를 지정한다.
- AI가 많이 지적했다고 좋은 리뷰라고 평가하지 않는다.
- 테스트 통과나 AI의 “문제 없음”을 단독 종료 기준으로 쓰지 않는다.
- 몇 달 동안은 프롬프트를 자주 바꾸지 않는다. 그래야 결과를 비교할 수 있다.

## 마지막으로 기억할 것

이 운영안은 AI 리뷰가 사람보다 우수하다는 주장도 아니고, Claude와 Codex를 반드시 정해진 횟수만큼 써야 한다는 규칙도 아니다.

현재 알고 있는 위험을 피하면서 우리 프로젝트의 데이터를 모으기 위한 시작점이다.

당장 기억해야 할 것은 세 가지면 충분하다.

1. AI가 지적한 것은 아직 사실이 아니다.
2. AI 리뷰 결과를 사람 확인 없이 자동 수정으로 연결하지 않는다.
3. 리뷰 횟수보다 실제로 확인된 결함과 사람이 들인 시간을 기록한다.

실제 작업용 프롬프트와 기록표는 `ai-code-review-pilot-playbook.md`를 사용한다.

