AI 리뷰 코멘트에 자동 대응하는 CI 설계: GitHub Actions로 '무한 루프 방지, 파괴 방지, 비용 폭발' 구현하기
요약
AI 리뷰 코멘트를 자동으로 대응하는 CI 시스템 설계 방법을 다룹니다. AI가 지적 사항을 수정하고 푸시할 때 발생할 수 있는 무한 루프, 파괴적인 코드 변경(force push), 그리고 비용 폭발 문제를 워크플로우 구조와 가드 설계를 통해 방지하는 구체적인 YAML 및 스크립트 예시를 제시합니다.
핵심 포인트
- AI 자동 수정 시 발생하는 3가지 위험(루프, 파괴, 비용)을 경고함.
- 가장 중요한 것은 AI의 출력에 의존하지 않고 워크플로우 구조로 가드를 놓는 것임.
- GitHub Actions 토큰 및 리뷰어 조건을 활용하여 무한 루프를 방지하는 것이 핵심임.
- Claude 실행 시 `--max-budget-usd`와 같은 비용 제어 옵션을 반드시 사용해야 함.
당사(合同会社ジョインクラス)는 사내 업무의 약 98%를 launchd의 정기 잡(scheduled job)과 Claude Code의 무인 실행으로 처리하고 있습니다. PR에도 AI 리뷰를 도입했지만, 당분간은 지적 사항에 대한 대응만 사람이 하는 상태였습니다.
'이 null 체크가 빠졌어요', '이 변수명이 이해하기 어려워요' 정도의 지적에 매번 브랜치를 체크아웃하여 수정하고 push하는 과정. 이것은 자동화할 수 있을 것입니다.
하지만 아무 생각 없이 '리뷰 코멘트가 오면 Claude에게 고치게 한다'를 만들 경우, 다음 세 가지 사고가 발생합니다.
- 무한 루프: AI가 수정 push → AI 리뷰 재실행 → 또 지적 → 또 수정... -
- 파괴: AI가 임의로
git push --force등을 실행하거나 관련 없는 파일을 덮어쓰는 것- - 비용 폭발: 한 번 호출 비용이 예상보다 높고, 이것이 루프와 곱해지면서 발생하는 비용 증가
필자는 실제로 2번을 저질렀습니다. 로컬 무인 실행에서 AI가 git push --force를 실행했고, 브랜치가 사라졌습니다. 이 글은 그 반성을 바탕으로 3가지 사고를 워크플로우 구조로 방지하는 설계를, 바로 사용할 수 있는 YAML과 스크립트로 소개합니다.
[AIレビュアー] --review comment--> [GitHub]
dim pull_request_review / pull_request_review_comment
▼
...
핵심은 'AI에게 부탁해서 지키게 하는' 것이 아니라, AI가 무엇을 출력하더라도 사고가 발생하지 않는 위치에 가드(guard)를 놓는 것입니다. 프롬프트에서의 금지 조항은 보조적인 역할에 불과합니다.
CI 버전을 작성하기 전에, 당사에서 매일 작동하는 무인 실행 래퍼(wrapper)를 소개합니다. CI 버전은 이를 거의 그대로 이식했습니다.
#!/bin/bash
# claude를 무인 실행할 때의 공통 래퍼. 실제 비용을 기록함.
_CLAUDE_RUN_LIB="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
...
호출 측은 다음과 같습니다 (기사 자동 생성 잡의 실 코드).
claude_run replenish --effort low --allowedTools "Write,Read,Edit" -p "..."
여기서 얻은 교훈이 3가지 있습니다.
- 실제로 측정해보니 '2+2'를 물어보는 것만으로도 1회 $0.27~$0.47가 들었습니다. 내역의 대부분은 캐시 생성에 사용된 약 41,000 토큰이었고, 자사의 CLAUDE.md나 스킬은 5,800 토큰뿐이었습니다. 나머지는 고정 오버헤드이므로,
--max-budget-usd는 반드시 붙여야 하며 줄일 수 있는 것은 호출 횟수뿐입니다. CI에서는 이것이 루프 횟수의 상한 설계에 직결됩니다. - 표준 출력의
--output-format json으로 비용을 가져오는total_cost_usd를 기록해 두면, 나중에 '어떤 잡(job)이 비싼지' 알 수 있습니다. - 인증을 읽지 않는
--bare는 사용하지 마세요.Not logged in상태로 실패합니다 (필자는 이것으로 하룻밤 분량의 잡 전체를 망쳤습니다).
.github/workflows/ai-review-fix.yml 파일을 만듭니다.
name: ai-review-fix
on:
pull_request_review:
...
루프 방지는 3중으로 했습니다.
| 계층 | 메커니즘 | 멈추는 경우 |
|---|---|---|
| 토큰 | GITHUB_TOKEN으로의 push는 새로운 워크플로우를 시작하지 않음 (GitHub 사양) | 수정 push로 AI 리뷰가 자동 재실행되지 않음 |
| 발언자 | review.user.login != 'github-actions[bot]' | 자신의 코멘트에 반응하지 않음 |
| 횟수 | ai-fix-round-N 레이블로 상한 3회 | AI 리뷰어가 다른 토큰으로 매번 지적해도 3회에서 멈춤 |
1계층만으로 충분해 보일 수도 있지만, AI 리뷰어를 PAT나 GitHub App으로 구동하는 경우 수정 push를 감지하여 재리뷰합니다. 횟수 상한은 어떤 구성에서도 작동하는 마지막 방어선이므로 반드시 넣어주세요. 상한에 도달하면 실패시키고 사람에게 통보하는 것이 정답입니다.
#!/bin/bash
set -euo pipefail
COMMENTS_FILE="$1"
...
설계상의 포인트:
–
。
--allowedTools
에서 Bash와 Write를 빼는 Edit은 기존 파일의 덮어쓰기만 가능하기 때문에, 신규 파일 생성이나 git 작업은 물리적으로 할 수 없습니다. git push --force 같은 사고는 '금지'하는 것이 아니라 'Bash를 전달하지 않음'으로 방지합니다.
–
'지적이 틀렸다면 고치지 않는다'는 것을 명시해야 합니다. AI 리뷰는 오탐지도 합니다. 맡겨만 두면, 올바른 코드를 망가뜨리고 지적에 맞추려는 동작을 하게 됩니다. 대응하지 않은 이유가 PR 커멘트에 남기 때문에, 인간은 그 부분만 보면 됩니다.
–
상한선(limit)이 계산 가능하다는 것이 중요합니다. --max-budget-usd 1
× 상한 3회 = 1 PR당 최대 $3
AI의 출력을 신뢰하지 않고, 결과의 차이분으로 판정합니다.
#!/bin/bash
set -euo pipefail
# 건드려서는 안 되는 경로
...
.github/을 보호하는 것은, AI가 자신의 워크플로우를 수정하여 가드를 해제하지 못하게 하기 위해서입니다. 사소하지만 가장 중요한 부분입니다.
구현할 때 막히기 쉬운 점들을 정리합니다.
–
。
리뷰에서 5건 지적되면 5개로 병렬 실행됩니다. pull_request_review_comment으로 시작하면, 커멘트 1건마다 잡이 돌아가는 pull_request_review의 submitted로 받고, 그 리뷰의 커멘트를 모아서 가져오는 것이 정답입니다.
–
수정 중인 잡(job)이 취소되고, 중간 상태에서 다음 것이 실행됩니다. concurrency에 cancel-in-progress: true를 하지 않으면 –
fork PR을 대상으로 삼지 않습니다. pull_request_target으로 바꾸면 secrets는 사용할 수 있지만, 제3자의 코드를 쓰기 권한과 함께 실행하게 됩니다. 외부 기여자(contributor)의 PR은 사람이 대응하는 것이 좋습니다.
–
테스트를 AI 수정 후에 반드시 실행합니다. 테스트가 실패하면 push하지 않으므로, 망가진 코드가 PR에 쌓이지 않습니다.
도입했다면, 일부러 지적을 내는 PR로 다음 4가지를 확인해 보세요.
# 1. 테스트용 브랜치에 명백한 지적이 나오는 코드를 넣는다
git switch -c test/ai-fix
echo 'export const f = (x) => x.length' > src/tmp.ts
...
확인할 것은 4가지입니다.
– 수정 커밋이 1개 쌓이고,
ai-fix-round-1 라벨이 붙는 것 – 수정 push 후에 워크플로우가 재시작하지 않는 것 – 같은 리뷰를 3번 달면, 4번째에서 '중단했습니다' 커멘트가 뜨며 멈추는 것
–
.github/을 변경하도록 지적을 내면, verify-diff로 실패하는 것
특히 2와 3은 루프 방지 확인이므로, 본 서비스 도입 전에 반드시 통과시켜야 합니다.
당사는 예전에 AI가 작성한 영업 메일을 확인하지 않고 자동 전송하여, 거래처에 경어 사용이 어색한 메일이 도착한 적이 있습니다. 그 이후로 대외 액션은 모두 draft → 승인 → 실행 과정을 거치고 있습니다.
이번 CI도 같은 생각입니다. AI에게 리뷰 대응을 맡기지만, 병합할지 여부는 인간이 결정합니다. AI가 담당하는 것은 '수정'과 '수정하지 않은 이유를 작성'하는 것까지입니다.
자동화는 AI의 능력을 제한하기 위한 것이 아니라, 안심하고 맡길 수 있는 구조입니다. 가드를 구조로 넣어두면, AI의 출력이 다소 흔들려도 사고가 나지 않습니다.
이 글에서는 '리뷰 지적에 대한 대응'만 다루었지만, 요구사항 정의 → 설계 → 구현 → 리뷰 → 수정 개발 라이프사이클 전체를 AI 전제하에 재구성하는 방법은 저서 『AI 구동 개발 라이프사이클(AI-DLC)의 교과서』에서 체계적으로 정리했습니다. CI에 리뷰를 포함시키거나, 인간이 판단해야 할 지점을 분리하는 것도 다루고 있습니다.
도서 목록은 여기 → https://zenn.dev/joinclass?tab=books
AI 자동 생성 콘텐츠
본 콘텐츠는 Qiita AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기