"Claude가 코드를 더 잘 읽을 수 있다"는 것이 사실일까? 실무 컴파일러를 이용한 중복 검출 벤치마크로 Gemini와 비교해 본 결과
요약
작성자는 실무 컴파일러 코드를 대상으로 중복 검출 벤치마크를 제작하여 Claude와 Gemini의 성능을 비교했습니다. 그 결과, Claude가 Gemini Flash보다 눈에 보이는 차이가 있는 중복을 약 2배 많이 발견하는 것으로 나타났습니다. 또한, 저렴한 Haiku 모델도 Sonnet과 유사한 수준의 높은 검출 능력을 보였습니다.
핵심 포인트
- Claude는 Gemini Flash 대비 '같은 규칙' 중복 발견율이 약 2배 높음.
- '같은 규칙을 다른 방식으로 구현한 중복'에서 Claude가 강점을 보임.
- 저렴한 Haiku 모델도 Sonnet과 비슷한 수준의 검출 능력을 가짐.
- Claude는 지시 범위를 벗어나지 않으려는 시스템적 안정성이 높음.
"코드를 다루게 한다면 Claude가 Gemini보다 낫다"라는 이야기를 자주 듣습니다. 평소에는 Claude와 Gemini 둘 다 사용하면서 C#에서 GPU용 코드를 생성하는 자체 컴파일러를 개발하고 있습니다. 체감상으로는 확실히 차이가 있습니다. 단순히 읽게 하는 것을 넘어, 쓰게 해도 Claude의ほうが 질이 높고 리팩토링할 필요가 없는 완성도 높은 코드를 작성합니다. 너무 긴 메서드가 적고 설계가 깔끔합니다. 다만, 이 느낌만으로는 남에게 설명하기 어렵습니다.
그래서 코드 리뷰 도구를 만드는 김에, 실제로 작동하는 프로젝트 코드 중에서 '같은 규칙이 2개 이상의 위치에 쓰여진 중복'을 찾아내게 하는 벤치마크를 만들고, Gemini와 Claude에게 같은 조건으로 풀어보게 했습니다.
먼저 결론부터 말씀드리겠습니다.
결론: 눈에 보이는 차이가 있는 중복은 Claude가 Gemini Flash보다 약 2배 많이 발견했습니다.
- 가장 큰 차이를 보인 부분은 '같은 규칙을 다른 방식으로 구현한 중복'(예: 같은 전개를, 한쪽은 C#의 구문 트리(AST)로, 다른 쪽은 C++ 문자열로 조립하는 경우)이었습니다. 정답 12개 그룹 중, Claude Sonnet은 평균 6.3개 그룹을, Gemini Flash는 2.7~3.7개 그룹을 발견했습니다.
- Gemini Flash는 '제시한 지적이 맞는 비율'은 높지만(high에서 93%), 회차에 따라 제시하는 건수가 4건이거나 29건으로 편차가 큽니다.
- Claude Haiku는 발견한 중복의 총수에서는 Sonnet과 비슷한 수준을 보였습니다. 이 작업에서의 단가는 Sonnet의 약 1/4입니다(프롬프트가 10만 토큰을 초과하기 때문에, Haiku의 높은 쪽 단가를 기준으로 합니다).
- 추가로, 중복을 조사하는 과정에서 '중복된 2개 위치의 동작이 이미 서로 어긋나 있는' 버그 후보가 여러 개 발견되었습니다.
가장 중요한 수치를 도표로 나타내면 다음과 같습니다(각 모델 3회 평균).
결론 1: 눈에 보이는 차이가 있는 '같은 규칙' 중복은 Claude가 Gemini Flash보다 약 2배 많이 발견했습니다.
결론 2: 중복의 총수에서도 Claude가 약 2배 많았습니다. 저렴한 Haiku도 Sonnet과 비슷한 수준이었습니다.
아래에 실무에서의 인상, 벤치마크 제작 방법, 사용된 프롬프트, 결과 순으로 작성하겠습니다.
여기는 벤치마크가 아니라, 매일 사용하는 과정에서 느낀 개인적인 인상입니다.
Claude는 사양을 전달하지 않았더라도 '여기는 2곳에서 다루는 방식이 다르니, 한쪽이 버그가 아닐까'라고 지적합니다. 이번 벤치마크에서도 중복을 찾아보라만 했는데도, '이 두 가지는 같은 규칙이어야 하는데, 한쪽만 검사가 빠져있다'라는 지적이 여러 번 나왔습니다(후술).
Claude의 auto 모드에는 도구 실행을 사전에 심사하는 메커니즘이 있습니다. 실제로 작업 중에 에이전트가 아직 명시적으로 승인하지 않은 커밋을 실행하려 했을 때, 이 심사 과정에서 막혔습니다. 제가 '앞으로는 커밋까지 자동로 해도 좋다'라고 말할 때까지는 그러한 종류의 조작은 통과되지 않았습니다. '요청하지 않은 것은 하지 않는다'가 시스템적으로 보장되는 점은 실무에서 매우 도움이 됩니다.
Gemini는 요구사항 정의를 상세하게 다듬어 나갈수록, 어느 시점에서 요청하지 않은 구현이나 커밋/PR 생성을 시작하는 경우가 잦았습니다. 이번 벤치마크에서도 프롬프트로 금지했던 명령어 실행(환경 변수를 읽으러 가는 것)을 한 번 수행했습니다. 결과에는 영향을 주지 않는 범위였지만, 지시 범위를 벗어나려는 경향은 느껴집니다.
- 실작 중인 C# 기반 컴파일러(C#를 GPU용 CUDA C++ 코드로 변환하는 트랜스파일러)의 리포지토리입니다. 100% LLM이 작성한 프로젝트입니다. 인간은 한 줄도 코드를 쓰지 않았습니다. 아직 출시된 것은 없지만, 리포지토리는 공개되어 있습니다: https://github.com/kassyi/Henicos
- 그중에서 81개 파일, 약 72만 바이트(대략 18만 토큰)를 골랐습니다.
정답 중복을 포함한 파일: 29개 파일 -
같은 폴더에 있지만, 중복을 포함하지 않은 비슷한 역할을 하는 파일: 52개 파일 (미끼)
- C# 외에도 CUDA용과 CPU용의 C++ 헤더(
.cu
,
.hpp
)를 포함합니다.
「의도적으로 중복을 심는」 것도 고려해 보았으나, 심은 중복은 부자연스러워지기 쉽습니다. 그래서 이 프로젝트의 issue에 기록되어 있던 「하나의 규칙이 여러 장소에 구현되어 있어, 한쪽만 수정하면 버그가 발생하는」 중복을 정답으로 삼았습니다. 과거에 실제로 버그를 유발했던 종류의 중복입니다.
-
issue에서 가져온 중복은 14쌍입니다.
-
C# 규칙의 중복: 12쌍 (예: 호출 그래프를 추적하는 처리가 3개의 분석에 각각 존재함, 동일한 매크로 전개가 C# 버전과 C++ 버전에 있음)
-
C++의 CPU용 및 CUDA용 정의의 중복: 2쌍
-
여기에 Gemini가 실행으로 찾아냈고 사람이 코드로 확인한 C++ 중복 5쌍을 나중에 추가하여, 정답은 총 19쌍이 되었습니다. 이 5쌍은 Gemini가 발견한 것이므로, 정답은 다소 Gemini 쪽으로 치우쳐 있습니다. 따라서 비교에서는 C#의 12쌍 결과를 주요 지표로 삼았습니다.
-
모든 모델에 동일한 프롬프트를 전달했습니다(아래 참조).
-
「파일을 분할하지 않고 전부 읽고 답변할 것」「답변이 담긴 폴더, issue, git 히스토리를 보지 말 것」「검색 자동화를 하지 말 것」이라고 지시했습니다.
-
각 모델을 3번씩 실행했습니다.
| 모델 | 사고의 깊이 | 실행한 환경 |
|---|---|---|
| Gemini 3.8 Flash | medium | Antigravity의 새로운 채팅 |
| ... | ||
| Claude 쪽은 effort를 지정하지 않고 시작했기 때문에, Claude Code가 서브 에이전트에 사용하는 기본 깊이로 작동하고 있습니다. Gemini처럼 깊이를 조절하여 비교하지는 않았습니다. |
전체적인 흐름은 다음과 같습니다.
-
정답과의 대조: 예측 위치 중 2곳 이상에서 정답의 다른 위치와 「동일한 파일의 행 범위가 겹치는」 경우, 해당 정답을 발견했다고 간주했습니다(Node 스크립트로 기계적으로 판정).
-
정답에 없는 예측 심사: 정답과 일치하지 않은 예측은 전체 모델 합쳐서 240건이 있었습니다. 여기에는 실제 중복도 많이 포함되어 있습니다. - 같은 중복을 가리키는 것들을 위치의 겹침으로 묶어 80건으로 줄였습니다.
-
어떤 모델의 예측인지 출처를 숨기고, 순서도 섞어서 2명의 심사위원에게 개별적으로 판정하게 했습니다. 심사위원은 Claude Opus 5.5와 Gemini 4 Argon입니다. 한쪽 제조사의 모델만으로 심사를 진행하면 불공평하므로, 양사에서 각각 1명씩 배치했습니다. - 판정은 「실제」「약함(실제이나 작음)」「오류」의 3가지로 나뉩니다. 기준은 「한쪽을 변경했을 때, 다른 쪽도 변경하지 않으면 동작이 달라지는가」입니다.
-
심사 통합: 두 심사위원의 판정이 갈린 경우는 사람(글쓴이)이 코드를 열어 결정했습니다.
파일 경로는 일반화했습니다.
핵심은 「전부 읽고 답변할 것」「답변이나 히스토리를 보지 말 것」「같은 규칙이 다른 방식으로 구현된 것을 찾을 것」「위치를 행 번호가 포함된 JSON으로 반환할 것」의 4가지입니다. 모든 모델에 동일한 프롬프트를 사용했습니다. 출력 경로만 모델별로 변경했습니다.
전체 프롬프트 전문 (클릭하여 열기)
당신은 코드 리뷰의 중복 탐지 담당자입니다. 다음 작업을 이 순서대로 끝까지 수행해 주세요.
대상
<대상 목록 파일>에 적힌 파일만 대상입니다(1행 1파일, 리포지토리 루트 기준 상대 경로). 먼저 대상 목록을 읽고 언급된 파일을 모두 읽어주세요. 청크로 나누지 말고, 전부 다 읽은 후에 답변합니다. 대상이 아닌 파일은 읽지 마십시오.
...
{
"pairs": [
{
"locations": [
{ "path": "src/...", "symbol": "타입.멤버", "startLine": 10, "endLine": 40 },
{ "path": "src/...", "symbol": "타입.멤버", "startLine": 55, "endLine": 90 }
],
"reason": "어떤 규칙이 중복되는지, 1~2문장으로 작성하세요.",
"confidence": "high"
}
]
}
locations는 2개 이상이어야 합니다.path는 리포지토리 루트 기준 상대 경로(/ 구분). 행 번호는 실제로 파일을 열어 확인한 해당 부분의 시작 행과 종료 행(1부터 시작)입니다.confidence는high/medium/low중 하나를 사용합니다.- 중복이 발견되지 않으면 "pairs": []"라고 작성해 주세요. 억지로 언급하지 마십시오.
...
핵심은 '출처를 추측하지 않는다', '설명을 믿지 않고 반드시 코드를 열어 확인한다', '한쪽을 변경하면 다른 쪽도 변경할 필요가 있는지로 판별한다'의 세 가지입니다.
프롬프트 핵심 내용 (클릭하여 보기)
당신은 코드 중복을 지적한 후보를 1건씩 판단하는 심사위원입니다. 읽기만 하고 코드는 변경하지 않습니다.
- 후보를 제시한 사람이 누구인지는 숨겨져 있습니다. 설명의 작성 방식이나 언어로부터 출처를 추측하지 마십시오.
설명은 정확하지 않을 수 있습니다. 반드시 코드를 열어 확인해 주십시오.
...
- 80건 중, 3단계 판단까지 일치한 건수는 51건(64%)이었습니다.
- '진짜인지 오류인지'의 이분법적 판별에서는 65건(81%)이 일치했습니다.
- 갈린 15건은 필자가 코드를 확인하여 결정했으며, Claude 측을 따른 것이 7건, Gemini 측을 따른 것이 8건이었습니다. 어느 한쪽 심사위원이 일방적으로 옳다고 할 수는 없었습니다.
- 확정된 결과는 진짜 35건, 약함 27건, 오류 18건입니다.
'발견한 중복'의 분모는 정답인 19쌍에, 심사에서 진짜 또는 약하다고 판단된 55건을 더한 74건입니다.
| 모델 | 발견한 중복 (74건 중) | C# 규칙 중복 (12쌍 중) | 지적의 적중률 |
|---|---|---|
| Gemini 3.8 Flash(medium) | 18.7(428) | 3.7(16) | 85%(7196) |28) | 2.7(2
| Gemini 3.8 Flash(high) | 13.7(54) | 93%(89100) |
| Claude Sonnet 5.5(medium) | 33.7(3137) | 6.3(67) | 88%(8490) |41) | 5.0(3
| Claude Haiku 5.5(medium) | 34.7(307) | 87%(7992) |
회차별 편차도 도표로 나타내면 차이가 잘 보입니다. Claude의 두 모델은 세 번 모두 30건대에 머물렀고, Gemini Flash는 회차에 따라 크게 변동했습니다.
결론 3: Claude는 매번 30건대에서 안정적입니다. Gemini Flash는 4건일 때도 있고 28건일 때도 있어 편차가 큽니다.
- C# 규칙의 중복에서 차이가 나타남: '호출 그래프를 추적하는 처리가 3개의 분석에 각각 존재함', '동일한 매크로 전개를 C# 구문 트리와 C++ 문자열 두 가지 방식으로 구성하고 있음'과 같이 작성 방식이 다른 중복을 Claude는 안정적으로 포착했지만, Gemini Flash는 거의 포착하지 못했습니다. 모델에게 맡기고 싶은 것은 바로 이러한 '겉보기에는 다르지만 동일한 규칙'의 중복입니다.
- Gemini Flash는 적게 내고 빠뜨리지 않음: 맞는 비율은 high가 가장 높습니다. 다만, 제시하는 건수가 회차에 따라 4건에서 29건까지 크게 변동했습니다. 많은 건수를 제시했던 회차는 Claude와 비슷한 수준이었습니다.
- 사고 방식을 medium에서 high로 해도 늘지 않음: 3회 평균으로 볼 때, 오히려 high가 더 적은 경향을 보였습니다.
- Haiku의 가성비(Cost Performance)는 높음: 발견한 총 건수는 Sonnet과 비슷했습니다. 다만, 지적 오류가 많은 회차가 있었습니다.
- 정확한 위치를 기재할 수 있는가: 단 한 번, Haiku가 중복 자체는 찾았으나 줄 번호가 어긋나 있어 정답과의 기계적인 대조에 실패한 경우가 있었습니다. 심사에서 진짜로 간주되어 총 건수에는 포함되었지만, 도구로 사용하려면 줄 번호의 정확성도 중요합니다.
1M 토큰당 비용(입력 / 캐시 읽기 / 출력)은 다음과 같습니다.
| 모델 | 입력 | 캐시 읽기 | 출력 |
|---|---|---|---|
| Gemini 3.8 Flash | $0.75 | $0.1875 | $3.75 |
| ... |
회차당 비용입니다.
| 모델 | 사용한 토큰 | 회차당 비용 |
|---|---|---|
| Gemini 3.8 Flash (medium) | 입력 132만(그중 캐시 99만), 출력 1.8만 | 약 $0.50 |
| ... |
- Gemini의 2행은 첫 번째 실행 내역을 계산한 값입니다(캐시 유지료 미포함).
- Claude 측은 서브 에이전트의 총 토큰 수만 파악할 수 있어, 입력/캐시/출력 내역 구분이 어렵습니다. 따라서 출력은 2~3만 토큰으로 추정하고, 입력은 모두 캐시에서 읽힌 경우를 하한선, 전부 신규 입력인 경우를 상한선으로 폭을 제시했습니다.
- 어느 모델이나 1회당 1달러 전후로 유지되므로, 이 과제에서는 비용보다는 발견 능력의 차이가 더 크다고 할 수 있습니다.
- 참고로, 심사위원 Claude Opus 5.5(입력 $4.00 / 출력 $20.00)는 80건의 심사를 통해 총 26만 토큰을 사용했으며, 비용은 약 $1~$1.5였습니다.
중복을 찾게 한 모델과 심사위원은 '중복된 두 동작이 이미 서로 상충한다'는 지적을 요청하지 않았음에도 내놓았습니다. 이를 14건 수집하여 각각 코드로 확인한 결과는 다음과 같습니다.
| 결과 | 건수 |
|---|---|
| 새로운 문제로 등록함 | 3 |
| ... | |
| 새롭게 등록된 3건은 예를 들어 다음과 같은 경우입니다. |
- 경계(스레드 동기화)를 포함하는 함수를 호출이 아닌 '메서드 그룹'으로 전달할 경우, 경계에 도달하는지 분석이 이를 놓치는 경우가 있습니다. 다른 분석은 메서드 그룹도 세고 있어, 두 분석에서 '무엇을 호출로 간주할지'가 상충합니다.
- 특정 LINQ 연산자의 술어(predicate) 버전만 해당 실행 시의 함수가 준비되어 있지 않은 경우입니다.
'명세서를 주지 않아도 버그 후보를 찾아 제안해 온다'는 첫인상은 맞았습니다. 하지만 14건 중 새로운 문제는 3건이었고, 나머지는 확인해보니 문제가 아니었습니다. LLM의 '여기는 버그일 것이다'라는 지적은 좋은 조사 시작점에는 될 수 있지만, 그대로 믿어서는 안 된다는 것이 이번 학습 내용입니다. 참고로 인간 리뷰를 최소화하기 위해 서브 에이전트를 가동하여 제로 컨텍스트 상태에서 두 번째 리뷰를 진행하면 신뢰도가 상당히 높아집니다.
오직 하나의 리포지토리(repository), 하나의 이슈(issue)에 대한 결과입니다. 다른 언어나 다른 종류의 리뷰에서는 같은 차이가 나타나지 않을 수 있습니다.
실행 환경이 다릅니다: Gemini는 Antigravity를, Claude는 Claude Code의 서브 에이전트를 사용하여 구동했습니다. 파일 읽기 방식 등 도구 작동 방식의 차이도 결과에 포함되어 있습니다.
정답은 약간 Gemini에 가깝습니다: 나중에 추가된 5세트는 Gemini가 발견한 C++의 중복입니다.
**심사는 2명이 진행했으며, 일치율은 두 가지 선택지(이분법적)로 81%**입니다. 의견이 갈린 15건은 필자가 결정했습니다.
각 모델을 3회씩 사용했기 때문에, 평균 차이 중 작은 부분(예: Sonnet과 Haiku의 총 개수 차이 등)은 오차 범위 내에 있습니다.
여기부터는 전적으로 개인적인 추측입니다.
Google은 Gemini 단일 성능으로 승부하기보다는 Google One 등 여러 서비스를 묶어 판매하는 방향에 힘을 쏟는 것처럼 보입니다. 한편 Google은 Anthropic에 출자하고 컴퓨팅 자원도 제공하고 있다고 보도되었습니다. 경쟁 모델을 내부에서 볼 수 있는 입장에서, 여전히 단독적인 경쟁을 피하고 묶음 상품 쪽으로 기울고 있다면, "모델 자체의 성능만으로는 부족하다"는 것을 Google 스스로 느끼고 있을지도 모른다고 생각합니다. Gemini 3.1 Pro부터 Gemini 4 Argon에 이르기까지도, 외부에서 보기에는 상당히 고전했던 것처럼 보였습니다.
물론, 이번 벤치마크는 단 하나의 과제에 대한 작은 비교일 뿐입니다. 심사위원으로서의 Gemini 4 Argon은 Claude Opus와 거의 같은 정확도로 판정할 수 있었으며, 의견이 갈린 건 중 절반 이상에서는 필자가 Gemini 쪽을 선택했습니다. "Claude가 더 우수하다"고 단언하기보다는, "코드 중복을 읽어내는 과제에 있어서는 Flash급 모델끼리 비교했을 때 Claude가 좀 더 안정적이고 깊게 읽어낼 수 있었다"가 이번 결과로 말할 수 있는 범위라고 생각합니다.
- 실제 컴파일러 코드를 사용하여 이슈에 기록된 실제 중복을 정답으로 하는 중복 탐지 벤치마크를 만들었습니다.
- 동일한 프롬프트를 각 3회씩, 두 회사(사)의 심사를 통해 가려진 상태로 비교했습니다.
- '표현 방식만 다른 동일 규칙'의 중복에서는 Claude Sonnet이 Gemini Flash보다 약 2배 많이 발견했습니다.
- Gemini Flash는 적게 내고 빼놓지 않는 경향을 보여, 건수 편차가 큰 결과였습니다.
- 중복을 찾도록 시키는 것만으로도 실제 버그 후보를 찾아낼 수 있었습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Qiita AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기