Coding Agent 모델은 어떻게 고를까? SelfBench로 9개 실제 저장소를 비교해 봤다
Coding Agent 모델을 고르는 과정은 처음 보면 꽤 단순합니다. SWE-bench나 커뮤니티 리더보드를 보고 점수가 가장 높은 모델을 선택한 뒤, Codex나 Claude Code 같은 harness를 프로젝트에 붙이면 될 것처럼 보입니다.
저도 공개 리더보드는 계속 봅니다. 후보를 빠르게 줄이는 데는 분명히 유용합니다. 하지만 실제로 오래 유지할 저장소 안에 모델을 넣는 순간 질문이 달라집니다. TypeScript 중심인지 Python 중심인지, 테스트에서 브라우저나 Postgres, Redis를 띄워야 하는지, 실제 변경이 UI·캐시·SQL·빌드 시스템 중 어디에 많이 몰리는지, 과거 merged PR의 난이도 분포가 어떤지까지 영향을 줍니다.
공개 benchmark 하나가 이 모든 조건을 대신 답해 주기는 어렵습니다.
최근 Show HN에서 SelfBench를 봤습니다. 또 하나의 통합 리더보드를 만드는 대신, 내 저장소에서 실제로 merge된 PR을 Coding Agent eval task로 바꾸고 같은 task set에서 model, harness, reasoning effort, cost를 비교하는 방식입니다.
제가 먼저 확인하고 싶었던 것은 하나였습니다. 저장소가 달라지면 정말 모델 순위도 바뀌는가?
2026-10-07 기준 SelfBench가 공개한 9개 repository release를 모두 가져와 별도로 재분석했습니다. 공개 task 일부는 instruction, test patch, gold patch를 읽었고, upstream guardrail도 source code 수준에서 확인했습니다.
결과는 repo-specific eval의 가치를 꽤 잘 보여 줬습니다. 동시에 더 강한 문장을 쓰기는 어렵다는 점도 분명해졌습니다. 가장 높은 accuracy를 내는 setting은 저장소마다 달라졌지만, 현재 release는 task가 수십 개 수준이라 몇 퍼센트포인트 차이만으로 “이 모델이 확실히 더 강하다”고 말하기에는 아직 표본이 작습니다.
SelfBench의 핵심은 과거 PR을 내 저장소의 task distribution으로 바꾸는 데 있다
SelfBench는 사람이 만든 generic coding puzzle에서 출발하지 않습니다. 실제 저장소에서 이미 merge된 변경을 재료로 씁니다.
대략적인 흐름은 다음과 같습니다.
```text merged PR ↓ 변경 전 base commit으로 복원 ↓ engineering request에서 instruction 생성 ↓ held-out tests + reference patch 준비 ↓ smoke / nop / oracle / determinism ↓ independent reviewer ↓ Harbor task로 export ↓ 같은 task를 여러 model / harness / reasoning setting으로 실행 ↓ accuracy와 cost 비교 ```
기반이 되는 Harbor task format은 이런 목적에 잘 맞습니다. instruction, container environment, tests, solution이 분리되고, agent는 자기 작업 환경에서 구현한 뒤 verifier가 held-out material로 결과를 평가합니다.
SelfBench는 여기에 “과거 PR을 benchmark task로 생산하는 층”을 추가합니다.
PR history가 어느 정도 쌓인 팀이라면 이 차이가 큽니다. 모델이 다른 사람이 정의한 문제만 푸는 것이 아니라, 팀이 실제로 merge해 온 변경을 상대하게 됩니다. 디렉터리 구조, dependency, 테스트 관행, 프로젝트의 오래된 engineering constraint까지 task distribution에 같이 들어옵니다.
공개 리더보드에서 내 기술 스택과 비슷한 프로젝트를 몇 개 찾는 것보다 더 직접적인 평가입니다.
그래서 저는 public benchmark가 쓸모없다고 보지 않습니다. 역할을 앞단으로 옮기면 됩니다. 공개 결과로 shortlist를 만들고, 최종 default는 내 저장소의 task로 결정하는 방식입니다.
9개 저장소를 비교했더니 계속 1위를 유지한 setting은 없었다
당시 SelfBench public result API에는 9개 저장소가 있었습니다. 각 release의 task count, passed, accuracy, model, harness, reasoning level, cost-per-task를 내려받아 다시 계산했고, published accuracy가 실제로 `passed / tasks`와 일치하는지도 확인했습니다.
최고 accuracy setting은 다음과 같았습니다.
| 저장소 | Task 수 | 최고 accuracy setting |
|---|---|---|
| vercel/next.js | 38 | GPT-6.1 Sol / Codex / High — 84.2% |
| PostHog/posthog | 36 | Claude Opus 5.5 / Claude Code / High — 69.4% |
| earendil-works/pi | 50 | GPT-6 Sol / Codex / High — 84.0% |
| getsentry/sentry | 81 | Claude Opus 5.5와 Claude Sonnet 5.5 / Claude Code / High — 82.7% 공동 1위 |
| mupt-ai/self-bench | 38 | GPT-6.1 Sol / Codex / High — 76.3% |
| vercel/eve | 38 | Claude Opus 5.5 / High와 GPT-6.1 Sol / Low — 73.7% 공동 1위 |
| vercel/vercel | 47 | Claude Opus 5.5 / Claude Code / High — 80.9% |
| supabase/supabase | 36 | 4개 setting이 77.8%로 공동 1위 |
| pingdotgg/t3code | 39 | Claude Opus 5.5 / Claude Code / High — 76.9% |
동률을 포함하면 9개 저장소에서 6개의 서로 다른 exact top setting, 5개의 winner model family가 나왔습니다. 모든 저장소에서 계속 1위를 한 완전한 setting은 하나도 없었습니다.
같은 setting이 여러 repository에 나타나는 경우를 대상으로 상대 순위의 Spearman rank correlation도 계산했습니다. 저장소 pair별 상관은 약 0.462에서 0.995 사이였고 중앙값은 0.807이었습니다.
이 결과는 “저장소마다 리더보드가 완전히 뒤집힌다”는 뜻은 아닙니다. 강한 모델은 대체로 여전히 강합니다. 다만 “공개 리더보드 1위면 내 저장소에서도 그대로 1위”라고 가정할 만큼 안정적이지는 않습니다.
그래서 지금은 “어떤 Coding Agent 모델이 가장 강한가?”보다 다음 질문이 더 실용적이라고 봅니다.
이 저장소, 이 실제 변경 분포, 이 harness, 이 비용 예산에서는 어떤 setting이 더 맞는가?
여기서 model name만 보는 것은 부족합니다. SelfBench가 model, harness, reasoning effort를 함께 하나의 setting으로 다루는 이유도 그 때문입니다. 같은 모델도 harness나 effort를 바꾸면 accuracy와 cost가 함께 움직일 수 있습니다.
“Claude vs GPT”만 남기면 이미 중요한 비교 축 하나를 버리는 셈입니다.
비용 쪽에서는 오히려 꽤 안정적인 결과가 나왔습니다. 제가 본 9개 release 모두에서 가장 저렴한 model family는 GPT-6 Luna였습니다. 다만 Low / High reasoning setting은 저장소마다 달랐습니다.
이 역시 2026-10-07 시점의 snapshot일 뿐입니다. provider pricing, reasoning 설정, task 길이는 바뀝니다. 재사용할 만한 것은 “accuracy × cost의 Pareto frontier를 본다”는 방법이지, 오늘의 cost-per-task 숫자를 외우는 것이 아닙니다.
현재 결과는 SelfBench public directory에서 직접 확인할 수 있습니다.
제 표현을 바꾸게 만든 결과: 9개 모두 1위와 2위가 깔끔하게 분리되지 않았다
위 표만 보면 “Next.js에는 GPT-6.1 Sol이 더 맞고, PostHog에는 Claude Opus가 더 맞다”고 쓰기 쉽습니다.
방향성은 이해할 수 있지만, 확신의 강도가 너무 큽니다.
현재 release의 task 수는 36~81개뿐입니다.
그래서 각 setting의 `passed / tasks`를 이용해 Wilson 95% interval 기반의 작은 표본 sensitivity check를 했습니다. benchmark task가 엄밀한 IID sample이라고 가정한 것도 아니고, 공식적인 significance test를 하려는 것도 아니었습니다. 보고 싶은 것은 하나였습니다. 리더보드에서 몇 퍼센트포인트 차이만 나는 경우, 작은 표본의 불확실성을 넣으면 그 격차가 얼마나 단단해 보이는가?
결과는 0 / 9였습니다.
9개 저장소 중 어느 것도 1위 setting의 interval이 2위 setting의 interval보다 완전히 위에 있지 않았습니다.
Next.js를 보면 1위는 32/38, 84.2%입니다. 2위는 30/38, 78.9%입니다. 리더보드에서는 5.3%p 차이지만 descriptive interval은 여전히 크게 겹칩니다.
Sentry는 더 가깝습니다. 67/81은 82.7%, 66/81은 81.5%입니다. 이 결과만 보고 “Claude Sonnet이 GPT-6.1 Sol을 확실히 이겼다”고 쓰면, 리더보드가 제공하지 못하는 확신까지 만들어 내는 셈입니다.
이 말은 모델 차이가 없다는 뜻이 아닙니다. SelfBench가 의미 없다는 뜻도 아닙니다.
오히려 repo-specific eval이 모델 선택을 실제 engineering에 더 가깝게 만듭니다. 다만 수십 개 task 수준의 리더보드는 방향성 evidence로 쓰는 편이 맞습니다. 누가 크게 뒤처지는지, 누가 Pareto frontier에 들어가는지, 어떤 setting을 내 저장소에서 다시 돌려 볼지 판단하는 데는 유용합니다. 2%나 5% 차이로 장기 승자를 선언하는 도구는 아닙니다.
팀 기본 모델, 큰 규모의 routing, 구매 결정처럼 영향이 큰 선택이라면 저는 task 수를 늘리고 trial을 반복하고 batch가 바뀌어도 ranking이 안정적인지 확인하겠습니다.
내 private leaderboard를 한 번 돌린 뒤 장기 winner를 정하는 것은 public leaderboard를 한 번 보는 것과 본질적으로 크게 다르지 않습니다.
자동 생성 benchmark에서 더 무서운 것은 agent cheating보다 grader bias다
SelfBench를 볼 때 처음부터 신경 쓰였던 설계가 하나 있습니다. task authoring agent가 원래 완료된 PR을 볼 수 있다는 점입니다.
편리한 구조입니다. 완료된 변경에서 instruction, tests, reference solution을 만들어야 하기 때문입니다. 하지만 benchmark 설계 측면에서는 분명한 위험이 생깁니다. hidden tests가 gold implementation에 너무 밀착되면 task가 “요구사항을 만족하라”가 아니라 “원 작성자의 구현을 재현하라”로 변할 수 있습니다.
SelfBench도 이 문제를 분명히 의식하고 있습니다. upstream을 commit `67242b85569ea0c27af0c68bd2769ed2d02a05c4`에 고정한 뒤 README 설명이 아니라 source code를 확인했습니다.
확인한 guardrail은 다음과 같습니다.
- static audit가 gold patch와 held-out test patch의 file overlap을 막는다
- verifier가 agent가 변경한 held-out path를 복원하고 grading 전에 보호한다
- nop gate에서 base snapshot은 새 test에 실패해야 하고 기존 regression은 계속 통과해야 한다
- oracle gate에서 reference patch 적용 후 통과해야 하며 fail-to-pass를 반복해 determinism을 확인한다
- independent reviewer prompt가 다른 방식의 올바른 구현도 이 test를 통과해야 한다고 명시한다
또 Next.js 2개, Sentry 2개 task를 골라 instruction, test patch, gold patch를 읽었습니다. third-party repository code는 실행하지 않았습니다.
4개 샘플 모두 구조 검사를 통과했습니다. test와 gold의 파일 경로 overlap은 0, instruction에는 source PR number / GitHub URL / grader artifact name의 명백한 leakage가 없었고, environment image는 digest-pinned였으며 held-out path protection과 benchmark canary도 있었습니다.
수동으로 읽었을 때도 gold에만 존재하는 private helper를 hidden test가 요구하는 식의 노골적인 coupling은 찾지 못했습니다.
예를 들어 Next.js stale-cache task는 stale-while-revalidate, 같은 key에 대한 중복 revalidation 방지, root-param key 독립성 같은 외부 동작을 요구합니다. hidden tests는 실제 app fixture와 cache API를 통해 그 동작을 검사하고, gold patch는 내부 cache wrapper를 바꿉니다.
Sentry의 dropped-data UI task는 설명 문구를 검사할 때도 특정 한 문장을 그대로 요구하지 않고 비교적 유연한 semantic regex를 사용했습니다.
좋은 방향의 grader 설계입니다.
하지만 4개 task는 어디까지나 4개 task입니다. 전체 generation pipeline이 항상 공정하다는 증거는 아닙니다. Authoring agent가 완료된 implementation을 본다는 정보 우위는 남아 있습니다. mechanical rule과 reviewer는 coupling risk를 낮출 수 있지만 논리적으로 완전히 없애지는 못합니다.
training contamination도 따로 봐야 합니다.
SelfBench는 공개 task에 benchmark canary를 넣고 검색 엔진에 쉽게 노출되지 않도록 합니다. 이후 filtering이나 contamination detection에는 도움이 됩니다. 하지만 benchmark가 만들어지기 전부터 공개되어 있던 원본 PR, 코드, discussion이 과거 training data에 없었다는 사실까지 증명할 수는 없습니다.
따라서 “내 저장소에서 만든 benchmark”가 곧 “contamination-free benchmark”는 아닙니다. private repository는 이 위험을 낮추지만 source code, credential, data governance 문제를 더 신경 써야 합니다.
저는 이렇게 쓰겠습니다: public leaderboard로 후보를 줄이고, 내 저장소로 default를 정한다
이 분석을 마친 뒤 저는 오히려 public coding-agent benchmark를 계속 볼 생각입니다. 다만 마지막 결정까지 맡기지는 않을 겁니다.
개인용 작은 프로젝트이고 merged PR이 거의 없거나, Coding Agent를 가끔 쓰는 정도라면 repo-specific eval을 직접 만드는 비용이 더 클 수 있습니다. 공개 benchmark에서 2~3개 후보를 골라 실제 사용성과 가격을 확인하는 것만으로도 충분할 때가 많습니다.
반대로 여러 model이나 harness를 동시에 쓰고 있고, API 비용이 무시하기 어려워졌고, 팀 공통 default agent를 정해야 하고, 저장소에 수십~수백 개의 대표적인 merged PR이 있고, test environment를 안정적으로 재현할 수 있거나 model routing을 만들고 있다면 이야기가 달라집니다. 이때는 “무슨 task를 어떤 setting에 보낼 것인가”가 중요해집니다.
그래도 처음부터 거대한 benchmark를 만들지는 않겠습니다.
먼저 실제 작업 분포를 대표하는 PR을 고릅니다. task instruction과 hidden tests를 사람이 검토합니다. 그 다음 accuracy, cost, failure pattern, setting ranking의 안정성을 봅니다. task를 더 넣거나 반복 실행해도 같은 흐름이 유지되는지 확인합니다.
SelfBench는 이 흐름을 이미 충분히 잘 구현하고 있어서 이 글을 위해 비슷한 companion repository를 하나 더 만들 필요는 없었습니다. 구현은 mupt-ai/self-bench에서 바로 볼 수 있습니다. instruction, environment, solution, verifier가 어떻게 분리되는지 더 알고 싶다면 Harbor Task Structure가 다음 읽을거리입니다.
문제가 한 단계 아래, 즉 “Agent가 만든 테스트 자체를 믿을 수 있는가?”라면 이전에 진행한 Mutation Testing 첫 번째 A/B 실험도 관련이 있습니다. 새 Codex 모델이 발표됐는데 client에 보이지 않는 것이 문제라면 Codex Model Catalog + Sub2API 원명 passthrough를 참고할 수 있습니다.
SelfBench에서 제가 얻은 가장 큰 결론은 그날 어떤 모델이 1위였는지가 아닙니다.
모델 선택을 “다른 사람의 리더보드에서 평균적으로 얼마나 잘하는가”에서 한 단계 더 나아가 “내가 실제로 merge하는 종류의 코드 변경에서 이 setting이 어떻게 동작하는가”로 바꿀 수 있다는 점입니다. 그리고 나머지 절반도 같이 기억해야 합니다. agent를 평가하는 것만큼 agent를 평가하는 benchmark도 평가해야 합니다. 그래야 repo-specific eval이 또 하나의 비싼 리더보드 신앙이 아니라 실제 engineering decision 도구가 됩니다.