AI 에이전트가 만든 PR을 검토하고 불필요한 변경을 제거하는 방법
AI 코딩 에이전트가 만든 Pull Request를 병합 전에 검토하는 실전 절차입니다. 승인 기준을 고정하고 전체 diff를 읽으며, 새 컨텍스트의 리뷰 에이전트에게 근거를 요구하고, 승인된 항목만 작은 단위로 줄인 뒤 동일한 검증을 반복하고 사람이 최종 승인합니다.
목차

AI 코딩 에이전트는 오류를 빠르게 고치거나 기능을 구현할 수 있습니다. 하지만 요청과 무관한 파일을 포맷하고, 추상화를 추가하고, 설정을 바꾸거나, 작업에 필요한 범위보다 훨씬 넓게 코드를 다시 쓸 수도 있습니다. 병합 전 목표는 단순히 줄 수가 가장 적은 diff가 아닙니다. 중요한 모든 변경이 합의된 요구사항과 연결되고, 유지보수자가 자기 말로 설명할 수 있으며, 테스트나 다른 증거로 검증할 수 있는 상태가 목표입니다.
한 개발자는 X에서 개인적인 방법을 공유했습니다. 에이전트가 PR을 만든 뒤 새 컨텍스트에서 두 번째 에이전트를 실행해 무엇을 줄이거나 제거할 수 있는지 찾게 한다는 방식입니다. 작성자는 추가 작업과 토큰이 필요하며 보장된 최적해가 아니라고 명시했습니다. 다른 사용자는 Codex가 많은 오류를 고쳤지만 코드 전체를 크게 바꾸어 더 이상 이해하기 어려워졌다고 보고했습니다. 이 사례들은 문제를 보여 주지만, 두 번째 에이전트가 항상 PR을 개선한다는 증거는 아닙니다.
아래 절차에서 두 번째 에이전트는 비판적인 리뷰어일 뿐 결정권자가 아닙니다. 범위, 증거, 위험, 병합 결정은 사람이 책임집니다.
7단계 전체 흐름
- 승인 계약을 작성합니다. 기대 동작, 바뀌면 안 되는 동작, 허용 범위, 위험, 검증 명령을 고정합니다.
- Conversation, Commits, Checks, Files changed와 로컬 Git 명령으로 실제 변경 목록을 만듭니다.
- 새 컨텍스트의 에이전트에게 첫 번째 패스는 검토만 시키고 편집을 금지합니다.
- 각 발견을 유지, 단순화, 제거, 별도 PR 분리, 사람 판단으로 분류하고 근거를 요구합니다.
- 사람이 승인한 축소만 작고 되돌릴 수 있는 묶음으로 적용합니다.
- 축소 전후에 같은 관련 테스트와 검사를 실행합니다.
- 최종 diff를 처음부터 다시 읽고 유지보수자가 전체를 설명할 수 있을 때만 병합합니다.
1. 두 번째 검토 전에 승인 계약을 작성하기
“이 PR을 더 깔끔하게 만들어라”는 목표는 너무 모호하고 또 다른 주관적 재작성을 부를 수 있습니다. 짧은 계약에 다음을 포함합니다.
- 문제와 관찰 가능한 결과: 사용자나 호출자가 무엇을 보게 되는가.
- 보존할 동작: 기존 인터페이스, 실패 동작, 호환성, 데이터 의미.
- 허용 범위: 변경이 예상되는 모듈, API, 스키마, 설정, 테스트.
- 명시적 비목표: 프레임워크 업그레이드, 전역 포맷, 무관한 이름 변경, 추측성 추상화, 필요 없는 마이그레이션 금지.
- 위험 제약: 보안, 권한, 마이그레이션, 성능, 관측성, 롤백, 하위 호환성.
- 검증: 저장소에서 실제로 쓰는 format, lint, type-check, unit, integration, build, migration, E2E 명령.
올바른 결과를 설명할 수 없다면 무엇이 불필요한지도 신뢰성 있게 판단할 수 없습니다. 먼저 계약을 명확히 하십시오.
2. 에이전트 요약이 아니라 전체 diff 확정하기
GitHub는 PR 증거를 여러 화면에 나눠 둡니다. Conversation에는 설명과 논의, Commits에는 브랜치 변화, Checks에는 자동 검증, Files changed에는 실제 diff가 있습니다. 공식 리뷰 흐름에서는 줄별 댓글, 수정 제안, 파일별 Viewed 표시, 최종 Comment·Approve·Request changes를 사용할 수 있습니다.
로컬에서 실행하거나 수정할 때 GitHub가 문서화한 방법은 다음과 같습니다.
gh pr checkout <PR_NUMBER>
git fetch origin
origin/main을 실제 base branch로 바꾸고 공통 조상부터 HEAD까지 확인합니다.
git diff --stat origin/main...HEAD
git diff --name-status origin/main...HEAD
git log --oneline origin/main..HEAD
Git 정의에서 git diff A...B는 A와 B의 merge base부터 B까지의 변경입니다. 요약을 본 뒤 전체 diff와 의심 경로를 읽습니다.
git diff origin/main...HEAD
git diff origin/main...HEAD -- path/to/suspicious-file
이 인벤토리 단계에서는 아직 삭제하지 마십시오. 파일을 다음처럼 분류합니다.
| 분류 | 확인 질문 |
|---|---|
| 핵심 구현 | 승인 계약의 항목을 직접 구현하는가? |
| 필요한 지원 | 테스트, 문서, 마이그레이션, 설정이 핵심 변경에 실제로 필요한가? |
| 범위 확장 의심 | 전역 포맷, 대규모 이름 변경, 무관한 추상화, 의존성 업그레이드가 포함됐는가? |
| 생성 산출물 | 소스와 함께 커밋해야 하는가, 실수로 들어왔는가? |
| 불확실·고위험 | 보안, 데이터, 호환성 또는 리뷰어가 모르는 영역을 건드리는가? |
복잡해 보인다는 이유만으로 중복이라고 판단할 수 없습니다. 방어 코드, 마이그레이션, 호환성 경로는 길어도 필요할 수 있습니다.
3. 새 컨텍스트의 첫 패스는 리뷰 전용으로 만들기
새 컨텍스트의 장점은 두 번째 에이전트가 본질적으로 더 정확해서가 아닙니다. 구현을 완성하는 대신 범위와 증거를 의심하는 다른 목표를 줄 수 있기 때문입니다. 이는 실무자 보고에 기반한 검토 기법이지 GitHub 필수 요구사항이나 측정된 보장은 아닙니다.
승인 계약, 전체 diff, 관련 호출부, 테스트, 저장소 규칙을 전달하고 다음과 같이 요청합니다.
당신은 이 Pull Request의 두 번째 유지보수자 리뷰어입니다. 목표는 코드를 다시 쓰는 것이 아니라 승인 계약을 유지하는 가장 작고 설명 가능한 변경 집합을 찾는 것입니다.
첫 번째 패스는 리뷰만 합니다. 파일을 수정하지 마십시오.
PR 목표, 전체 diff, 관련 호출부, 테스트, 저장소 제약을 읽으십시오.
각 발견에 대해 다음을 반환하십시오.
1. 파일과 정확한 hunk 또는 symbol
2. 변경이 충족하는 요구사항
3. 근거: caller, test, interface contract, documentation 또는 근거 없음
4. 제거 또는 단순화 위험
5. 조치: KEEP / SIMPLIFY / REMOVE / SPLIT / HUMAN DECISION
6. 변경 후 실행할 정확한 검증
규칙:
- 코드가 길거나 스타일이 다르다는 이유만으로 삭제를 권하지 말 것
- 테스트 통과를 요구사항이 맞다는 유일한 증거로 삼지 말 것
- 무관한 포맷, 중복 추상화, 미사용 helper, 범위 밖 refactor, 설명 없는 dependency/config 변경을 우선 점검할 것
- 반증이 없으면 보안, 호환성, 마이그레이션, 오류 처리, 관측성을 보존할 것
- 불확실성을 명시하고 비즈니스 규칙을 추측하지 말 것
- 낮은 위험부터 높은 위험 순서의 축소 계획으로 끝낼 것. 아직 코드를 쓰지 말 것
편집 전에 보고서를 받으면 “축소”를 명목으로 또 다른 대규모 재작성이 생기는 것을 막을 수 있습니다. 모든 제안은 파일, hunk, 근거를 가리켜야 합니다.
4. 사람이 근거로 각 발견을 분류하기
| 결정 | 적용 조건 | 확인할 근거 |
|---|---|---|
| 유지 | 계약 또는 필요한 보안, 호환성, 마이그레이션, 운영 동작 구현 | 요구사항 연결, 호출 경로, 테스트, 인터페이스, 문서화 제약 |
| 단순화 | 동작은 필요하지만 branch, wrapper, layer가 중복 | 전후 동작 동등성과 주요 경계 검증 |
| 제거 | 무관, 미사용, 계약 없음, 우연한 포맷/이름 변경 | 저장소 검색, build, 관련 테스트에서 의존성 없음 |
| 분리 | 가치가 있을 수 있으나 현재 계약 밖 | 독립적으로 설명, 테스트, 리뷰, revert 가능 |
| 상향 판단 | 낯선 도메인, 보안 경계, 마이그레이션, 숨은 규칙 | code owner, 도메인 담당, characterization test 필요 |
다음은 확인 신호이지 자동 삭제 규칙이 아닙니다. 하나의 호출을 위한 여러 범용 계층, 호환 기간 설명 없는 신구 경로, 무관한 포맷·import·이름·파일 이동, 설명 없는 의존성·lockfile·설정, 동작이 아닌 내부 모양을 검증하는 테스트, 모든 예외를 조용히 삼키는 처리, caller 없는 helper, “나중에 필요할지 모른다”는 코드입니다.
테스트가 없다는 사실도 미사용의 증거가 아닙니다. 커버리지 공백일 수 있습니다. 불확실한 동작을 제거하기 전에 characterization test를 추가하거나 모듈 담당자에게 확인하십시오.
5. 작은 묶음으로 줄이고 복구 지점 남기기
편집 전 working tree를 확인하고 로컬 백업 참조를 만듭니다.
git status --short
git branch backup/ai-pr-before-trim
파일 전체를 base 상태로 되돌릴 때:
BASE=$(git merge-base origin/main HEAD)
git restore --source="$BASE" -- path/to/unrelated-file
일부 hunk만 되돌릴 때:
git restore -p --source="$BASE" -- path/to/file
Git 문서에 따르면 추적 경로가 restore source에 없으면 source와 맞추기 위해 그 경로가 삭제될 수 있습니다. $BASE와 경로를 확인하고 실행 직후 diff를 보십시오. 수동 편집도 괜찮지만 새 범위 밖 refactor를 넣지 않는 것이 중요합니다.
승인된 그룹 하나씩 처리합니다.
git diff
git add -p
git diff --cached
git commit -m "Remove unrelated changes from AI-generated PR"
작은 commit은 무엇을 왜 제거했고 어떤 검증을 했는지 보여 줍니다. 리뷰 중 파괴적 history rewrite로 과정을 숨기지 마십시오.
6. 축소 전후에 비교 가능한 검증 실행하기
테스트 목적은 diff가 짧아졌음을 증명하는 것이 아니라 승인한 동작이 유지됐음을 증명하는 것입니다. 가능하면 원본 PR의 baseline을 기록하고 각 묶음 후 같은 관련 명령을 반복합니다.
<format-check-command>
<lint-command>
<typecheck-command>
<targeted-unit-test-command>
<relevant-integration-test-command>
<build-or-e2e-command>
명령은 저장소 문서나 CI에서 가져오고 에이전트가 추측하게 하지 마십시오. 정상 경로, 중요한 경계, 실패, 권한, 빈 값, 동시성, timeout, retry, 공개 인터페이스, 직렬화 형식, 마이그레이션, build, type, lint, security, 최신 commit의 필수 Checks를 다룹니다.
축소 후 테스트가 깨지면 해당 묶음을 되돌리거나 백업에서 복구하고 원인을 조사합니다. 승인 계약이 기존 기대가 잘못됐다고 명시하고 사람이 새 동작을 승인하지 않은 한, 초록색을 만들기 위해 테스트와 구현을 동시에 바꾸지 마십시오.
초록색 테스트는 중요한 증거지만 전체를 보장하지 않을 수 있습니다. 유지보수자의 이해가 여전히 필요합니다.
7. 최종 diff를 다시 읽고 명시적으로 결정하기
축소 후 Files changed를 다시 열어 모든 파일을 처음부터 검토합니다. GitHub는 이미 Viewed로 표시한 파일이 바뀌면 Viewed를 해제하므로 재검토할 파일을 찾는 데 도움이 됩니다. Commits와 Checks도 다시 확인해 최신 revision에 대한 결과인지 확인합니다.
최종 diff와 계약만 새 컨텍스트로 한 번 더 검토할 수 있지만 종료 조건을 둡니다. 근거 있는 문제만 보고하고 무한한 스타일 refactor를 시작하지 않도록 합니다. 그 다음 사람이 다음 결정을 제출합니다.
- Approve: 계약 충족, 변경 설명 가능, 위험 처리, 필수 검증 통과.
- Request changes: 범위 밖 변경, 불투명한 로직, 실패한 검사 남음. 실제 병합 차단 여부는 repository rules와 branch protection에 달려 있습니다.
- Comment: 유용한 피드백이지만 승인이나 공식 변경 요청은 아님.
병합 전 체크리스트
- 모든 변경 파일이 현재 요구사항, 필요한 테스트 또는 명시적 지원 작업과 연결된다.
- 유지보수자가 중요한 hunk를 에이전트 요약 없이 설명할 수 있다.
- 설명 없는 의존성, 설정, 권한, 마이그레이션, 생성 파일은 제거·분리·상향 검토했다.
- 원본과 축소 PR에 비교 가능한 검증을 사용했다.
- 로컬 테스트, build, 최신 commit Checks가 프로젝트 요구를 충족한다.
- 보안, 데이터, 호환성 불확실성을 적절한 담당자가 검토했다.
- diff가 여전히 넓다면 독립 작업을 분리했다.
- 리뷰 결정과 후속 작업을 기록했다.
흔한 실패와 복구
두 번째 에이전트가 모듈을 다시 쓰기 시작함
실행을 중단하고 편집 없는 보고서로 돌아갑니다. 접근 파일을 제한하고 모든 제안에 hunk, 요구사항, 검증을 요구합니다. 근거 없는 미적 refactor는 거절합니다.
에이전트들이 의견이 다름
투표하지 마십시오. 호출부, 인터페이스 계약, 실패 경로, 테스트, 과거 제약을 비교합니다. 근거가 약하면 코드를 잠시 유지하고 커버리지를 추가하거나 도메인 담당자에게 확인합니다.
테스트는 통과하지만 코드를 설명할 수 없음
커버리지는 이해 가능한 설계와 다릅니다. PR을 분리하고 문서를 추가하거나 핵심 경로 설명을 요구합니다. CI가 초록색이라는 이유만으로 불투명한 코드를 병합하지 마십시오.
신뢰할 테스트가 없음
보존할 동작에 대한 최소 characterization test 또는 반복 가능한 수동 검증과 기록을 만듭니다. 고위험 코드에서 증거 부족은 멈출 이유이지 추측할 허가가 아닙니다.
PR이 너무 큼
핵심 동작, refactor, 의존성 업그레이드, 포맷, 마이그레이션을 독립적으로 검토 가능한 변경으로 나눕니다. 작은 단위가 검증과 revert에 유리합니다.
승인된 발견을 실행하는 프롬프트
승인된 finding ID [LIST]만 구현하십시오.
목록 밖 파일을 수정하거나 기회성 refactor를 하지 마십시오.
각 논리 그룹마다:
1. 실제 diff를 보여 줄 것
2. 지정된 검증 명령을 실행할 것
3. 명령, exit status, 실패 요약을 보고할 것
4. 남은 불확실성을 나열할 것
항목이 승인 계약, 공개 interface, security 또는 migration 동작을 바꾸면 중단하고 사람의 결정을 요청하십시오.
핵심은 “에이전트를 더 쓰는 것”이 아닙니다. 생성과 검토를 분리하는 것입니다. 첫 컨텍스트는 구현을 제안하고, 두 번째 컨텍스트는 범위와 근거를 의심하며, 사람은 결정과 승인을 책임집니다. 올바른 결과는 가장 짧은 diff가 아니라 작업을 해결하는 가장 작고 설명 가능하며 검증된 변경입니다.
출처와 적용 범위
- 실무자 개인 보고: 새 컨텍스트 축소 리뷰에 관한 Arnav Gupta의 X 게시물과 답글. 일반 통계가 아닙니다.
- 사용자 보고: Codex의 광범위한 변경 뒤 코드를 이해하기 어려워졌다는 원문. 저장소, diff, 테스트 데이터는 공개되지 않았습니다.
- GitHub 공식 문서: PR 변경 검토, PR 로컬 checkout, Pull requests reference.
- Git 공식 문서: git diff, git restore.