왜 Claude Code는 단 하나가 중요할 때 여덟 개의 결과물을 내놓는가
요약
LLM 기반 코드 리뷰 도구인 Claude Code나 Cursor 사용 시 발생하는 과도한 제안(노이즈) 문제를 분석합니다. 모델의 '도움이 되려는' 특성으로 인해 심각한 결함보다 스타일 중심의 제안이 많아지는 구조적 한계를 다룹니다.
핵심 포인트
- LLM은 심각도 구분 없이 모든 잠재적 개선 사항을 제안하는 경향이 있음
- 코드 리뷰 시 스타일 제안 등 노이즈를 분류하는 데 많은 시간이 소모됨
- 프롬프트 엔지니어링만으로는 LLM의 정적 분석 노이즈를 완벽히 해결하기 어려움
- 전통적인 정적 분석 도구와 마찬가지로 AI 기반 도구도 높은 오탐률을 보임
풀 리퀘스트(Pull Request)를 엽니다. Diff(차이점)에 대해 Claude Code나 Cursor를 실행합니다. 기다립니다.
파일당 8개의 제안이 나옵니다. 어쩌면 그보다 더 많을 수도 있습니다. 다음과 같은 식입니다:
더 나은 조회 성능을 위해 여기에서 일반 객체 대신 Map 사용을 고려하십시오.이 함수는 명시적인 타입 어노테이션(Type Annotations)을 통해 이점을 얻을 수 있습니다.입력 배열이 비어 있는 경우를 처리하는 것이 좋을 수 있습니다.재사용성을 위해 이 로직을 별도의 함수로 추출하는 것을 고려하십시오.SQL 쿼리가 파라미터화 없이 사용자 입력을 연결하고 있습니다 — SQL 인젝션(SQL Injection) 가능성이 있습니다.← 진짜 중요한 것이 변수 이름은 더 서술적일 수 있습니다.이 함수에 JSDoc 주석을 추가하는 것을 고려하십시오.여기서 any를 사용하는 것은 타입 안전성(Type Safety)을 상실합니다.
다섯 번째 항목은 배를 멈춰 세울 만큼(ship-blocker) 중요한 문제입니다. 나머지 7개는 추측성이거나, 스타일 중심이거나, 혹은 당신의 것이 아닌 일반적인 코드베이스에 적용되는 내용입니다. 이를 종합하면: 개발자는 5번 항목에 도달하기 위해 1, 2, 3, 4, 6, 7, 8번 항목을 무시하는 데 분류(Triage) 시간의 80%를 소비합니다. 그리고 5번에 도달했을 때쯤이면, 이미 3분 내내
이것은 Claude Code나 Cursor의 특정 버그가 아닙니다. 범용 LLM (Large Language Model)을 코드 리뷰어 (Code Reviewer)로 사용할 때 나타나는 구조적 특성입니다. 모델의 인센티브 함수 (Incentive function, '도움이 되기')에는 "특정 심각도의 결함에 대해서만 말하기"와 구별되는 "실제 결함이 있을 때만 말하기" 모드가 존재하지 않습니다.
프롬프트 (Prompt)를 통해 노이즈를 약간 줄일 수는 있습니다. 예를 들어, 스타일 제안이 아닌 실제 버그만 표시해줘라고 요청할 수 있지만, LLM이 판단하는 "실제 버그"의 기준은 모호하며, 다음 응답에는 어쨌든 "var 대신 let을 사용하는 것을 고려하세요"와 같은 내용이 포함됩니다.
정적 분석 노이즈의 실제 형태
BrassCoders는 코드베이스별 정적 분석 (Static-analysis) 노이즈의 형태를 직접 측정합니다. 전형적인 실제 Python 프로젝트는 12개의 도구를 통해 약 1,500개의 가공되지 않은 스캐너 탐지 결과 (Scanner findings)를 생성하며, 이 중 관련성 순위 (Relevance ranking)를 통과하는 것은 약 30개 정도입니다. 아래의 가공되지 않은 출력물은 숙련된 정적 분석 스택이 기본적으로 생성하는 결과입니다.
- 비밀 정보 탐지 (Secrets detection): 800개의 일치 항목을 찾습니다. 대부분은 오탐 (False positives)입니다 (테스트 픽스처 (Test fixtures), 예시 값, 주석 내 해시 형태의 문자열 등).
- 개인정보 탐지 (Privacy detection): 300개의 일치 항목을 찾습니다. 대부분은 테스트 파일 내의 샘플 데이터입니다.
- 코드 품질 스캐너 (Code-quality scanners) (Bandit, Pylint): 200개의 항목을 표시합니다. 대부분은 정확성에 실질적인 영향을 미치지 않는 스타일 이슈입니다.
- AI 안티 패턴 스캐너 (AI anti-pattern scanner): 50개의 항목을 표시합니다. 그중 몇 개는 실제 문제 (입력값에 대한 eval 사용, 루프 내 문자열 결합 등)입니다.
- 유령 임포트 스캐너 (Phantom import scanner): 30개의 항목을 표시합니다. 약 15개는 실제로 깨진 임포트 (Broken imports)입니다.
총합: 약 1,380개의 탐지 결과. 실제 중요/높음 수준의 버그: 약 50개.
노이즈가 발생하는 이유는 스캐너가 나쁘기 때문이 아닙니다. detect-secrets는 훌륭하며, Bandit도 훌륭합니다. 노이즈가 발생하는 이유는 모든 유용한 스캐너들이 설계상 과도하게 트리거 (Over-trigger)되기 때문입니다. 이들은 실제 CVE (Common Vulnerabilities and Exposures)를 놓치느니 차라리 오탐을 발생시키는 쪽을 택합니다. 개별 스캐너는 각자 올바른 일을 수행하고 있습니다. 하지만 이들이 합쳐지면, 인간 리뷰어는 압도당하고 맙니다.
그 위에 AI 코드 리뷰 (AI code review)를 얹으면 문제는 더 악화됩니다. 이제 1,380개의 정적 분석 (static-analysis) 결과에 더해, LLM 기반 리뷰어가 파일당 8개씩 제안을 내놓게 됩니다. 50개 파일로 구성된 PR(Pull Request) 하나에는 '검토해야 할 사항'이 1,780개나 딸려 옵니다. 그 누구도 이 중 어느 것도 주의 깊게 살펴보지 않습니다.
실제로 작동하는 방식: 필터 계층 (Filter Layer) 추가
BrassCoders는 AI 코드 리뷰 문제를 탐지 (detection) 문제가 아닌 필터링 (filtering) 문제로 취급합니다. 구조적 통찰은 다음과 같습니다. 정적 분석 (static-analysis) 생태계는 이미 버그를 탐지하고 있으며, 병목 현상은 1,500개의 가공되지 않은 결과물을 개발자가 실제로 처리하는 30개로 변환해 주는 필터링 계층에서 발생한다는 것입니다.
개발자에게 필요한 것은 탐지 (detection) 단계 '이후'이자 분류 (triage) 단계 '이전'에 실행되는 계층입니다. 즉, 1,500개의 가공되지 않은 결과물을 받아 순위가 매겨지고, 중복이 제거되며, 프로젝트의 맥락을 반영한(project-aware) 약 300개의 결과물로 출력하는 계층입니다. 이것이 바로 BrassCoders가 하는 일입니다.
아키텍처는 다음과 같이 나뉩니다:
- 탐지 계층 (Detection layer, 무료 오픈 소스): 비밀 정보(secrets), 개인정보(PII), 코드 품질, AI 안티 패턴(AI anti-patterns), 오염 분석(taint analysis), 성능을 다루는 12개의 스캐너. 이들은 Bandit, Pylint, Pyre/Pysa, Semgrep, detect-secrets와 같이 통일된 출력 형식으로 연결된 범용 도구(commodity)들입니다.
- 필터링 계층 (Filtering layer): 우선순위 버킷 할당, 파일당 상한선 설정, 심각도 인지 노이즈 감소(severity-aware noise reduction). 휴리스틱(Heuristic) 버전은 오픈 소스(OSS) 코어에 포함됩니다. AI 기반 버전(의미론적 중복 제거(semantic dedup), 클러스터 크기 조정(cluster sizing), 프로젝트 시그니처 기반 재순위화(rerank-against-project-signature))은 월 12달러의 유료 플랜(Paid plan)에서 제공됩니다.
AI 단계는 탐지(detection)가 실행된 '이후'에 이루어집니다. 모델은 원본 소스 코드를 절대 보지 않습니다. 대신 메타데이터(파일 경로, 심각도, 스캐너, 코드 조각)가 포함된 범위가 지정된 결과물(scoped findings)을 보고, 어떤 것들이 동일한 근본 버그를 설명하는지 결정합니다.
실제 적용 사례
whisperx-production (약 2,000개의 파일로 구성된 실제 Python 프로젝트)에 BrassCoders를 실행해 보았습니다. 출력 결과:
🧹 Running intelligent optimization...
Intelligent optimization: 801 → 687 findings (14.2% reduction)
✨ Running AI enrichment...
...
12개의 스캐너(scanners)가 801개의 탐지 결과(findings)를 찾아냅니다. OSS-core 휴리스틱 필터(heuristic filter)가 명백한 노이즈를 제거하여 687개로 줄입니다. AI 인리치먼트(AI enrichment)가 중복을 제거(dedups)하고 순위를 매겨(ranks) 328개로 압축합니다. 이것이 개발자가 실제로 읽게 되는 생존자 세트(survivor set)입니다.
이 328개 중 상위 항목들은 실제적인 문제입니다:
🎯 Top Issues:
1. Broken Import: whisperx (critical)
2. Broken Import: pyannote.audio (critical)
...
각 항목은 스타일 선호도가 아닌, 즉시 배포해야 할 수정 사항입니다. 1,450개의 항목이 쏟아지는 파이프라인(firehose)이 4개의 우선순위 목록으로 정제되었습니다.
핵심 요약 (The Bottom Line)
BrassCoders는 AI 코드 리뷰 도구를 대체하는 것이 아닙니다. AI 어시스턴트(AI assistants)는 그 용도에 맞게 유용하지만(명백한 패턴 포착, diff 요약, 보일러플레이트(boilerplate) 생성 등), 그 출력물은 개발자가 분류 대기열(triage queue)로서 조치를 취하기 전에 필터링이 필요한 노이즈입니다.
BrassCoders는 바로 그 필터입니다.
- 무료 OSS 코어:
pipx install brasscoders
AI 코드 리뷰의 실패 모드(failure modes)에 대한 더 넓은 맥락은 AI Code Review: The Practical Guide for 2026를 참조하세요.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기