본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 06. 01. 06:42

AI 코드 리뷰 봇이 내 100개 이상의 PR을 리뷰했다 — 무엇이 맞고 틀렸는지에 대한 실제 데이터

요약

작성자가 100개 이상의 실제 오픈 소스 PR을 대상으로 AI 코드 리뷰 봇의 성능을 테스트한 결과입니다. AI 봇은 예외 체이닝 누락과 같은 미묘한 버그와 보안 문제를 정확히 잡아냈으나, 때로는 존재하지 않는 파일을 언급하는 환각 현상을 보이기도 했습니다.

핵심 포인트

  • CodeRabbit은 Python 예외 체이닝 누락 등 미묘한 버그를 정확히 포착함
  • 테스트 코드 내 환경 변수 설정과 같은 모듈 수준의 부작용을 감지함
  • AI 봇은 인간보다 빠르지만 존재하지 않는 파일을 지적하는 환각 현상이 있음
  • 실제 오픈 소스 기여 환경에서 AI 리뷰 도구의 실질적 효용성을 입증함

지난 30일 동안 저는 오픈 소스 프로젝트 전반에 걸쳐 100개 이상의 풀 리퀘스트 (Pull Requests, PRs)를 제출했습니다. 활발하게 활동하는 기여자에게는 흔한 일이지만, 제 코드를 리뷰하는 사람이 저뿐만이 아니었다는 점이 달랐습니다. **AI 기반 코드 리뷰 봇 (AI-powered code review bots)**이 모든 푸시 (push)를 지켜보고, 모든 디프 (diff)를 분석하며, 그 어떤 인간 리뷰어보다 빠르게 댓글을 달고 있었습니다.

결과는 다음과 같았습니다. 봇들은 제가 놓친 실제 버그를 잡아냈고, 제가 간과한 보안 문제를 표시했으며, 때로는 제 브랜치에 존재하지도 않는 파일에서 문제를 환각 (hallucination)하기도 했습니다. 이것은 2026년 현재 AI 코드 리뷰가 실제로 어떤 모습인지에 대한 정직하고 데이터에 기반한 이야기입니다.

설정: 3개의 봇, 100개 이상의 PR, 실제 리포지토리 (Repositories)

저는 통제된 실험을 수행한 것이 아니었습니다. 저는 바운티 (bounties)를 제출하고, 이슈 (issues)를 수정하며, 문서를 번역하는 등 실제 작업을 수행하고 있었습니다. 하지만 제가 기여한 리포지토리들은 우연히 다양한 AI 리뷰 도구들을 혼합하여 사용하고 있었습니다.

봇 (Bot)사용 중인 리포지토리리뷰된 PR 수인라인 댓글 (Inline Comments)정확도
CodeRabbitHELPDESK.AI, better-auth, Aigen-Protocol~60180+
...

이것들은 가공된 숫자가 아닙니다. 모든 댓글, 모든 플래그 (flag), 모든 "✅ Addressed in commit" 표시 모두 실제 유지 관리자 (maintainers)가 있는 실제 리포지토리의 실제 PR에서 나온 것입니다.

봇이 맞춘 것들 (긍정적인 면)

1. 예외 체이닝 (Exception Chaining) — 내가 몇 달 동안 놓쳤던 미묘한 버그

제가 HELPDESK.AI를 위해 작성한 Python 암호화 모듈에서 CodeRabbit은 다음과 같은 사항을 지적했습니다:

# 내가 작성한 코드:
except Exception as e:
    raise ValueError(f"Failed to decrypt data: {str(e)}")
...

차이점은 무엇일까요? 예외 체이닝 (Exception chaining) (from e)은 원래의 트레이스백 (traceback)을 보존합니다. 이것이 없으면 except 블록 내부에서 코드가 예외를 발생시킬 때 Python 3는 암시적으로 예외를 체이닝하지만, from e를 사용하면 이를 명시적으로 만듭니다. 프로덕션 환경의 암호화 실패를 디버깅할 때, 이는 "무언가 잘못되었다"와 "암호문이 변조되었기 때문에 GCM 태그 검증에 실패했다" 사이의 차이를 만들어냅니다.

CodeRabbit은 이를 P2 심각도 (P2 severity) 플래그로 포착하고 Ruff 규칙 B904와 연결했습니다. 저는 수년간 Python을 작성해 왔지만 from e를 일관되게 사용하지 않았습니다. 댓글 하나가 습관을 고쳐주었습니다.

2. 테스트에서의 모듈 수준 부작용 (Module-Level Side Effects) — 실제 오염 위험

같은 PR에서 CodeRabbit이 잡아낸 또 다른 사례입니다. 제 테스트 파일에는 다음과 같은 코드가 있었습니다:

# 내가 작성한 코드 (BAD):
import os
os.environ["AES_ENCRYPTION_KEY"] = "0123456789abcdef..."
...

문제는 모듈 임포트 시점에 환경 변수 (environment variables)를 설정하면 전체 pytest 프로세스에 걸쳐 상태 (state)가 유출된다는 점입니다. 만약 다른 테스트 모듈이 제 테스트가 실행되기 전에 encryption을 임포트하면, 제 테스트용 키를 가져가게 됩니다. 또한

  • 소스 코드 내 하드코딩된 API 키 (Hardcoded API keys) (Supabase anon keys, Firebase configs)
  • 인라인 스크립트 실행을 허용하는 CSP 헤더 누락 (Missing CSP headers)
  • 클라이언트 측 역할 확인이 서버 측에서 검증되지 않는 인증 우회 패턴 (Auth bypass patterns)
  • 로우 쿼리 빌더 (raw query builders) 내의 SQL 인젝션 벡터 (SQL injection vectors)

HELPDESK.AI의 보안 수정 사항에 대한 CodeRabbit 리뷰 중 하나는 authStorelocalStorage에 사용자 역할을 캐싱하고 있다는 점을 식별했습니다. 이는 사용자가 브라우저 저장소를 수동으로 편집하여 권한을 상승시킬 수 있음을 의미했습니다. 이 수정에는 모든 관리자 경로(admin route)에 대한 서버 측 역할 검증이 필요했는데, 이는 원래 개발자가 놓쳤던 부분이었습니다.

봇이 틀린 부분 (Bad)

1. 존재하지 않는 파일에 대한 환각 (Hallucinating Files That Don't Exist)

이것은 가장 흔하면서도 가장 위험한 실패 모드였습니다. CodeRabbit은 PR의 차이점(diff)뿐만 아니라 **전체 코드베이스 (entire codebase)**를 리뷰합니다. 이는 때때로 다른 브랜치의 파일을 참조할 수 있음을 의미합니다.

한 PR에서 CodeRabbit은 backend/sanitization.pysanitize_text()라는 함수를 참조하며 "차이 범위 외부 (outside diff range)"라는 코멘트를 남겼습니다. 제 브랜치에서 검색해 보았습니다:

grep -r "sanitize_text" --include="*.py"
# 결과 없음

해당 파일은 main 브랜치에는 존재했지만, 제 브랜치에서는 **이름이 변경 (renamed)**된 상태였습니다. 봇은 오래된(stale) 코드를 리뷰하고 있었던 것입니다. 만약 제가 봇의 제안을 맹목적으로 따랐다면, 존재하지 않는 함수를 참조하는 코드를 도입했을 것입니다.

교훈: 리뷰를 반영하기 전에 참조된 코드가 현재 브랜치에 실제로 존재하는지 항상 확인하십시오.

2. 분석으로 위장한 문맥 없는 린팅 (Context-Free Linting Masquerading as Analysis)

일부 CodeRabbit 코멘트는 본질적으로 자연어로 감싸진 Ruff/ESLint 출력 결과에 불과했습니다:

"정적 분석 (static analysis) 결과에 따라 (BLE001), 예외를 무분별하게 잡지 마십시오: Exception"

복호화 함수에서 Exception을 잡는 것은 의도적인 (intentional) 설계입니다. ValueError (잘못된 base64)부터 InvalidTag (변조된 암호문), OSError (읽을 수 없는 키 파일)에 이르기까지 모든 것을 포착해야 하기 때문입니다. 봇은 이것이 보안에 중요한 함수를 위한 의도적인 설계 선택임을 이해하지 못했습니다.

Ruff 규칙인 BLE001은 좋은 일반적인 가이드라인이지만, 문맥을 인식(context-aware)하지는 못합니다. 여러 실패 모드(failure modes)를 감싸는 최상위 복호화 함수에서 광범위한 예외(broad exceptions)를 포착하는 것은 방어 가능한 설계입니다.

3. 중복된 PR 제안 (Duplicate PR Suggestions)

HELPDESK.AI에서 저는 동일한 이슈(#916 — 분류기 서비스 테스트)에 대해 PR #924와 #927을 제출했습니다. #924가 저의 첫 번째 시도였고, #927은 개선된 버전이었습니다. CodeRabbit은 두 PR을 모두 리뷰하고 각각에 대해 서로 다른 수정 사항을 제안하여, 어떤 PR을 머지(merge)해야 하는지에 대한 혼란을 야기했습니다.

봇은 동일한 작성자가 동일한 이슈를 대상으로 하는 두 개의 PR이 존재한다는 것을 감지하여, 최신 버전만 리뷰하거나 중복임을 표시했어야 합니다.

4. 잘못된 보안 경고 (False Security Alerts)

환경 변수 설정을 추가하는 PR에서 CodeRabbit은 다음과 같이 표시했습니다:

"소스 코드에서 하드코딩된 Supabase anon key가 감지되었습니다."

하지만 이 "하드코딩된 키"는 실제로는 .env.example 파일의 기본값이었으며, 이는 프로덕션(production) 환경에서는 절대 사용되지 않는 플레이스홀더(placeholder)였습니다. 봇은 문맥을 이해하지 못한 채 eyJ...(Supabase 키의 base64 접두사) 패턴만을 매칭한 것이었습니다.

경쟁사 점수: 봇은 얼마나 빠른가?

놀라운 발견 중 하나는 AI 봇이 PR 제출 후 몇 분 이내에 리뷰를 완료한다는 점입니다. 제 PR에서 추출한 실제 타이밍 데이터는 다음과 같습니다:

제출된 PR첫 번째 봇 댓글시간 차이
HELPDESK.AI #925CodeRabbit2분 34초
...

첫 번째 리뷰까지 걸린 평균 시간은 2분 54초였습니다.

비교를 위해, 동일한 저장소(repo)의 인간 리뷰어들은 평균 2~7일이 소요되었습니다. 봇이 인간 리뷰어를 대체하는 것은 아닙니다. 대신 인간이 코드를 보기 전에 명백한 문제들을 잡아내는 1차 검토(first pass) 역할을 수행하고 있습니다.

"커밋에서 해결됨" 패턴 (The "Addressed in Commit" Pattern)

CodeRabbit에는 영리한 기능이 있습니다. 리뷰 댓글을 해결하는 수정 사항을 푸시(push)하면, 자동으로 댓글을 ✅ Addressed in commit <sha>로 업데이트합니다. 이는 명확한 감사 추적(audit trail)을 생성합니다.

하지만 여기에는 함정이 있습니다: 일부 댓글은 문제를 수정하지 않았음에도 자동으로 해결(auto-resolve) 처리됩니다. 브랜치에 어떤 커밋이라도 푸시하면, CodeRabbit은 다시 리뷰를 수행하며 해당 코드 주변이 변경되었을 경우 특정 이슈가 해결되지 않았더라도 이전 댓글을 해결된 것으로 표시할 수 있습니다.

댓글이 해결되었다고 가정하기 전에, 반드시 실제로 해결되었는지 확인하십시오.

실제 수치: 머지율(Merge Rate)에 미치는 영향

봇의 리뷰를 받은 PR과 그렇지 않은 PR의 머지율(merge rate)을 추적했습니다:

카테고리PR 수머지됨비율
봇 리뷰 완료, 모든 이슈 해결됨352880%
...

데이터는 명확합니다: 봇의 리뷰 내용을 반영하는 것은 머지 확률을 극적으로 높입니다. 봇이 지적한 모든 이슈를 수정한 PR은 이를 무시한 PR보다 3배 높은 비율로 머지되었습니다.

이는 타당한 결과입니다. 메인테이너(maintainer)들은 봇의 댓글을 보고 이를 품질 신호(quality signal)로 활용합니다. 만약 봇이 문제를 발견했는데 이를 수정하지 않았다면, 그것은 위험 신호(red flag)가 됩니다.

AI 리뷰 댓글의 세 가지 유형

230개 이상의 봇 댓글을 분석한 결과, 이를 세 가지 유형으로 분류했습니다:

유형 1: 실제 버그 (Genuine Bugs) (댓글의 40%)

이는 운영 환경(production)에서 문제를 일으킬 수 있는 실제 이슈들입니다:

  • 누락된 null 체크 (null checks)
  • 비동기 코드에서의 레이스 컨디션 (Race conditions)
  • 잘못된 타입 가정 (Incorrect type assumptions)
  • 이벤트 리스너에서의 메모리 누수 (Memory leaks)

조치: 항상 이를 수정하십시오.

유형 2: 스타일/컨벤션 위반 (Style/Convention Violations) (댓글의 35%)

이는 유효하지만 치명적이지는 않은 사항들입니다:

  • 예외 체이닝 패턴 (Exception chaining patterns)
  • 임포트 순서 (Import ordering)
  • 명명 규칙 (Naming conventions)
  • 사용되지 않는 변수 경고 (Unused variable warnings)

조치: 저장소(repo)의 스타일 가이드에서 요구하는 경우 수정하고, 그렇지 않으면 인지했음을 알리고 설명하십시오.

유형 3: 거짓 양성/환각 (False Positives/Hallucinations) (댓글의 25%)

이는 잘못되었거나 무관한 내용입니다:

  • 존재하지 않는 파일에 대한 참조
  • 의도된 패턴을 오해함
  • 문맥이 없는 린팅 규칙 (Context-free linting rules)
  • 오래된 코드 분석

조치: 근거와 함께 해당 제안이 왜 적용되지 않는지 정중하게 설명하십시오.

AI 리뷰어와 협업하는 방법 (대립하는 것이 아니라)

100개 이상의 PR (Pull Request)을 바탕으로 한 저의 워크플로우는 다음과 같습니다:

1단계: Push 및 대기

즉시 다른 작업을 시작하지 마십시오. 봇이 3분 이내에 댓글을 달 것입니다.

2단계: 각 댓글 분류

각 댓글을 검토하고 위에서 언급한 유형 1, 2 또는 3으로 분류하십시오.

3단계: 유형 1 수정, 유형 2 고려, 유형 3 대응

유형 3 (False Positives, 오탐)의 경우, 항상 근거를 들어 대응하십시오:

참조된 함수 `sanitize_text()`가 이 브랜치에 존재하지 않습니다.
이 리뷰는 다른 브랜치의 코드를 참조하고 있는 것으로 보입니다.

4단계: 수정 사항 Push 및 확인

Push한 후, 봇이 댓글을 "Addressed (해결됨)"로 표시하는지 확인하십시오. 그렇지 않다면 커밋 SHA (Commit SHA)와 함께 답장을 보내십시오.

5단계: 스레드 해결 (Resolve Threads)

GitHub API를 사용하여 리뷰 스레드를 해결하십시오:

gh api graphql -f query='mutation { resolveReviewThread(input: {threadId: "PRRT_...") { thread { isResolved } } }'

미래: AI 코드 리뷰가 나아갈 방향

저의 경험을 바탕으로 앞으로 다가올 변화는 다음과 같습니다:

1. 멀티 모델 합의 (Multi-Model Consensus)

단일 봇 대신, 저장소(Repo)에서 3~5개의 AI 리뷰어를 실행하고 여러 모델이 동의하는 문제에 대해서만 플래그(Flag)를 지정하게 될 것입니다. 이는 오탐(False Positives)을 획기적으로 줄여줄 것입니다.

2. 문맥 인식 보안 분석 (Context-Aware Security Analysis)

현재의 봇들은 보안 문제를 찾기 위해 패턴 매칭 (Pattern-matching)을 수행합니다. 미래의 봇은 전체 애플리케이션의 문맥 (Context)을 이해할 것입니다. 예를 들어, .env.example에 있는 Supabase 익명 키는 안전하지만, config.js에 있는 키는 안전하지 않다는 점을 인지하게 될 것입니다.

3. 자동 수정 제안 (Automated Fix Suggestions)

CodeRabbit은 이미 Diff (차이점)를 제안하고 있습니다. 1년 이내에 봇은 직접 수정을 적용하고 테스트를 실행하여 이를 검증할 수 있게 될 것입니다.

4. 리뷰 피로도 관리 (Review Fatigue Management)

봇이 더 상세하게 답변함에 따라, 개발자가 실제로 어떤 댓글에 조치를 취하는지 학습해야 할 것입니다. 사용자의 과거 수정률 (Fix rate)을 기반으로 한 개인화된 심각도 순위 (Severity rankings)를 기대하십시오.

결론

2026년의 AI 코드 리뷰 (AI code review)는 진정으로 유용하지만 불완전합니다. 봇들은 많은 인간 리뷰어들이 놓치는 예외 체이닝 (exception chaining), 테스트 격리 (test isolation), 의존성 불일치 (dependency mismatches)와 같은 실제 버그들을 잡아냅니다. 하지만 이들은 환각 (hallucinate)을 일으키기도 하고, 문맥 (context)이 부족하며, 때로는 단순히 채팅 인터페이스를 통해 린터 (linters)를 실행하는 수준에 그치기도 합니다.

승리하는 전략은 봇을 무시하거나 맹목적으로 따르는 것이 아닙니다. 그들을 주니어 리뷰어처럼 대하는 것입니다. 그들이 찾아낸 것을 존중하되, 제안을 검증하고, 그들이 틀렸을 때는 주저 없이 반박하십시오.

100개 이상의 PR (Pull Request)을 거친 후 내린 솔직한 평가는 다음과 같습니다: AI 코드 리뷰는 내 코드를 더 나아지게 만들었습니다. 봇이 나보다 똑똑해서가 아니라, 내가 너무 몰입해 있어서 보지 못하는 것들을 잡아내기 때문입니다. 그리고 리뷰어가 다른 시간대에 살고 있어 사흘 뒤에나 코드를 리뷰할 수도 있는 오픈 소스 (open source) 환경에서, 3분 만에 이루어지는 1차 검토는 매우 가치 있는 일입니다.

로봇이 코드 리뷰어를 대체하고 있는 것이 아닙니다. 로봇은 우리가 가진 리뷰어들을 더 효과적으로 만들고 있습니다.

여러분의 PR에서 AI 코드 리뷰 봇과 함께 작업해 보셨나요? 어떤 패턴을 발견하셨나요? 여러분의 경험을 댓글로 공유해 주세요. 함께 의견을 나누고 싶습니다.

AI 자동 생성 콘텐츠

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

원문 바로가기
0

댓글

0