핵심 요약
모든 PR에 인간 리뷰어 + AI 리뷰어 병행. AI는 24/7 즉시·일관성 우선, 인간은 비즈니스 맥락·아키텍처 판단. 둘 결합 시 PR 머지 속도 + 품질 동시 향상.
- 매일 50~200 PR — 인간 리뷰만으로는 한계
- Claude API로 평균 리뷰 비용 PR당 $0.30~$2
- false positive 관리가 도입 성공 핵심
1. 기본 워크플로
# .github/workflows/ai-review.yml
name: AI Code Review
on:
pull_request:
types: [opened, synchronize]
jobs:
review:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 0 }
- name: Get diff
run: |
git diff origin/${{ github.base_ref }}...HEAD > pr.diff
cat pr.diff | head -c 100000 > pr.diff.trimmed # 100K char 한도
- name: Run Claude review
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
run: |
python .github/scripts/review.py \
--diff pr.diff.trimmed \
--output review.md
- name: Post review comment
uses: actions/github-script@v7
with:
script: |
const fs = require('fs')
const review = fs.readFileSync('review.md', 'utf8')
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: review
})2. 리뷰 스크립트
# .github/scripts/review.py
import os, sys, anthropic
client = anthropic.Anthropic()
SYSTEM_PROMPT = """
당신은 시니어 코드 리뷰어입니다. PR diff를 검토하고:
1. 보안 이슈 (SQL injection, XSS, secret leak)
2. 성능 문제 (N+1, 메모리 leak)
3. 버그 가능성
4. 가독성·명명 개선
각 발견은 다음 JSON 형식:
{
"file": "경로:줄",
"severity": "critical|high|medium|low",
"category": "security|performance|bug|style",
"message": "설명",
"suggestion": "개선 코드"
}
모든 발견을 JSON array로 반환. 문제 없으면 [].
중요: 확실한 것만. 모호한 의심은 제외.
"""
def review(diff: str) -> list:
response = client.messages.create(
model="claude-opus-4-7",
max_tokens=4000,
system=SYSTEM_PROMPT,
messages=[{
"role": "user",
"content": f"PR diff:\n\n```diff\n{diff}\n```"
}]
)
return parse_findings(response.content[0].text)
def format_markdown(findings):
if not findings:
return "✅ 자동 리뷰: 발견된 문제 없음."
md = ["## 🤖 AI 코드 리뷰\n"]
by_severity = {"critical": [], "high": [], "medium": [], "low": []}
for f in findings:
by_severity[f["severity"]].append(f)
for sev in ["critical", "high", "medium", "low"]:
if not by_severity[sev]: continue
emoji = {"critical": "🔴", "high": "🟠", "medium": "🟡", "low": "🔵"}[sev]
md.append(f"\n### {emoji} {sev.upper()} ({len(by_severity[sev])})\n")
for f in by_severity[sev]:
md.append(f"**{f['file']}**: {f['message']}")
if f.get("suggestion"):
md.append(f"```\n{f['suggestion']}\n```\n")
return "\n".join(md)
if __name__ == "__main__":
diff = open(sys.argv[1]).read()
findings = review(diff)
md = format_markdown(findings)
open(sys.argv[2], "w").write(md)3. 비용 최적화
Prompt Caching
# 시스템 프롬프트는 cache_control
response = client.messages.create(
model="claude-opus-4-7",
system=[
{
"type": "text",
"text": SYSTEM_PROMPT,
"cache_control": {"type": "ephemeral"}
}
],
messages=[...]
)같은 시스템 프롬프트 반복 → 90% 비용 절감.
모델 라우팅
def select_model(diff: str):
lines = diff.count("\n")
if lines < 50:
return "claude-haiku-3-5" # 작은 변경
elif lines < 500:
return "claude-sonnet-4-6" # 일반
else:
return "claude-opus-4-7" # 큰 변경4. False Positive 관리
잘못된 리뷰 표시
PR 작성자가 AI 리뷰 코멘트에 reaction: 👎 → 학습 데이터 수집.
주간 false positive 리뷰
# cron: 매주 월요일
# 지난 주 reactions 분석
# false positive 패턴 식별 → 시스템 프롬프트 개선특정 패턴 화이트리스트
SYSTEM_PROMPT_ADDITIONS = """
다음은 우리 팀에서 의도적으로 사용하는 패턴이니 지적하지 마세요:
- forEach + await (배치 처리 의도)
- raw SQL (성능 critical 영역)
- console.log (디버깅 한정 디렉토리)
"""5. 단계별 적용
- Week 1-2: 모든 PR에 코멘트만, 차단 안 함
- Week 3-4: false positive 패턴 식별·수정
- Month 2: critical 등급은 머지 차단 (require-resolved)
- Month 3+: 자동 fix suggestion (Copilot Workspace 통합)
6. 보안 — secret 노출 방지
def sanitize_diff(diff: str) -> str:
# API key 패턴 마스킹
patterns = [
(r'sk-[A-Za-z0-9]{40,}', '[REDACTED]'),
(r'ghp_[A-Za-z0-9]{40}', '[REDACTED]'),
# ...
]
for pattern, replacement in patterns:
diff = re.sub(pattern, replacement, diff)
return diff7. 다국어 코드베이스
def detect_language(diff):
if '.py' in diff: return 'Python'
if '.tsx' in diff or '.ts' in diff: return 'TypeScript'
if '.go' in diff: return 'Go'
return 'mixed'
# 언어별 시스템 프롬프트 보강8. 메트릭
| 지표 | 측정 방법 |
|---|---|
| PR당 AI 리뷰 비용 | API usage / PR 수 |
| false positive율 | 👎 reactions / 전체 발견 |
| 인간 리뷰 시간 단축 | 도입 전후 PR 머지 시간 |
| 실제 버그 발견율 | AI 발견 → 인간 합의 비율 |
9. 한계
- 큰 PR (5000줄 이상)은 chunking 필요
- 비즈니스 로직 검증 못 함
- 아키텍처 결정 못 함
- 코드베이스 컨벤션 학습 어려움
10. 도구 비교
| 도구 | 특징 |
|---|---|
| 자체 구축 (이 글) | 완전 control, 비용 최저 |
| Greptile | SaaS, 코드베이스 학습 |
| CodeRabbit | SaaS, 한국어 약함 |
| GitHub Copilot Code Review | GitHub 통합, 단순 |
실측 — 도입 효과
| 지표 | before | after |
|---|---|---|
| PR당 인간 리뷰 시간 | 25분 | 10분 |
| 버그 머지 비율 | 2.4% | 0.8% |
| 리뷰 대기 시간 | 4시간 | 5분 (AI) + 2시간 (인간) |
| 월 비용 | 0 | $400 (200 PR) |

댓글 0