2369 단어
12 분
Edit 툴 4종, 880회 실측 성공률 — replace가 이긴 이유와 patch의 토큰 블랙홀
AI 이 게시글은 AI가 생성한 콘텐츠를 포함합니다.

Edit 툴 4종, 880회 실측 성공률 — replace가 이긴 이유와 patch의 토큰 블랙홀#

코딩 에이전트를 만들 때 “모델이 코드를 어떻게 수정하게 할까?”는 보통 구현 디테일로 취급된다. Git 스타일 unified diff(apply_patch)나 퍼지 매칭(patch)이 사람 개발자에게 익숙하다는 이유로 기본값이 되기 쉽다. 하지만 LLM은 코드를 토큰 스트림으로 본다. 줄 번호 오프셋 계산, 컨텍스트 매칭, hunk 헤더의 산수 실수가 쌓이면 단순한 “실패”가 아니라 비싼 재시도 루프로 이어진다.

이 글은 Oh My Pi 하네스가 제공하는 4가지 코드 편집 툴 — replace, hashline, apply_patch, patch — 의 성공률과 토큰·비용 효율을 11개 LLM × 20개 TypeScript 태스크, 총 880회 실행으로 실측한 결과다.

결론부터: replace가 평균 성공률 85.0%로 압도적이다. patch는 평균 성공률 68.2%로 오히려 2위인데도 입력 토큰이 replace의 3.05배, 성공 1건당 비용은 2.8배로 최악이다. 성공률만 보면 안 되는 이유가 여기 있다.


TL;DR#

평균 성공률11개 모델 중 최고 툴로 선택비용/성공
replace85.0%8/11$0.0094
hashline74.5%2/11$0.0118
apply_patch59.1%1/11$0.0228
patch68.2%0/11$0.0260
  • replace는 “실패의 하한선”이 가장 높다. 11개 모델 최저 성공률이 60% — 어떤 모델이든 어느 정도는 고쳐낸다.
  • patch는 어떤 모델에서도 최고 툴이 되지 못했고, 실패할 때마다 파일 전체 재독 → 더 큰 패치 재시도 루프로 토큰을 태운다.
  • hashline은 구조적 정밀도가 필요한 모델(kimi-k3, qwen3.7-plus)에서 강점을 보였다.
  • apply_patch는 mimo-v2.5 한 모델만 85%로 최고 툴로 선택 — 모델별 편향이 뚜렷하다.

1. 하네스의 4가지 edit 툴#

동작 방식장점실패 모드
replacepath, startLine, endLine, newText — 줄 범위를 통째로 교체컨텍스트 드리프트 없음, 지역 수정에 출력 토큰 최소줄 번호가 밀리면 off-by-one
hashline[파일#태그] 콘텐츠 해시 헤더 + SWAP/DEL/INS 연산스냅샷 검증이 결정적, 낡은 줄 번호에 면역해시 문법을 엄격히 따라야 함
apply_patch표준 unified diff (@@ -N,M +N,M @@)Git 형식, 학습 데이터에 익숙hunk 헤더 줄 수를 모델이 자주 잘못 계산
patcholdContext 문자열을 찾아 newContext로 교체줄 번호 불필요, 프롬프트가 직관적공백/들여쓰기 민감, 다중 턴 재시도 루프 유발

2. 측정 설계#

  • 스케일: 11개 모델 × 4개 툴 × 20개 태스크 = 880회 시도 (arm당 20회, best-of-1)
  • 태스크: 100% TypeScript — Core TS(45%), Express/Node(25%), React+TSX(20%), DOM+jsdom(10%). 난이도는 Easy 25% ~ Nightmare(10+ 파일 아키텍처 리팩터링) 10%
  • 검증: Docker verifier 컨테이너(--network=none)에서 tsc --noEmit + 숨은 동작 테스트. 모델이 자기 환경을 속일 수 없게 격리
  • 설정: 모든 실행은 --thinking off — 추론 토큰 노이즈를 제거하고 순수한 툴 콜·편집 정밀도만 측정
  • 비용: 공식 리스트 가격 기준. 429 쿼터 실패(인프라 원인)는 0토큰으로 제외, 에이전트 유발 재시도는 100% 부과

3. 툴별 성공률#

11개 모델 각각에서 해당 툴로 20개 태스크를 돌린 성공률의 평균·중앙값·하한·상한:

평균중앙값최저최고총 성공 / 220
replace85.0%85%60% (mimo-v2.5)100% (deepseek-v4-flash)187
hashline74.5%80%25% (qwen3.8-max)95% (deepseek-v4-flash)164
apply_patch59.1%65%0% (qwen3.8-max)¹90% (deepseek-v4-flash)130
patch68.2%70%35% (minimax-m3)85% (kimi-k3·qwen3.8-max·deepseek-v4-flash·deepseek-v4-pro)150

¹ qwen3.8-max × apply_patch arm은 토큰 0·비용 $0 — 쿼터/인프라 실패로 보이며 실측치가 아니다. 제외 시 apply_patch 평균은 65.0%.

여기서 가장 중요한 지표는 하한선(floor) 이다. replace는 가장 못하는 모델(mimo-v2.5)도 60%를 기록했다. 반면 hashline의 바닥은 25%, apply_patch는 사실상 측정 불가(0%)였다. 좋은 툴은 모델의 천장을 높이는 게 아니라 바닥을 끌어올린다 — 그리고 replace가 유일하게 그 역할을 했다.

흥미로운 반전: 모든 툴에서 가장 높은 성공률은 deepseek-v4-flash가 가져갔다 (replace 100%, hashline 95%, apply_patch 90%, patch 85% 공동 1위). 모델 역량이 받쳐주면 어떤 툴이든 잘 쓰지만, 툴은 모델의 바닥을 결정한다.


4. 토큰 & 비용: 성공률 너머#

성공률만 보면 patch는 2위다. 그런데 실제 지출을 보면 이야기가 완전히 달라진다 (44개 arm 합산):

총 입력 토큰총 출력 토큰캐시 읽기총 비용태스크당 입력평균 $/성공
replace4.26M197k6.89M$1.7819.4k$0.0094
hashline6.51M260k8.59M$2.0729.6k$0.0118
apply_patch8.82M243k12.07M$2.2640.1k$0.0228
patch13.01M376k16.79M$3.2859.1k$0.0260

patch는 태스크당 평균 59.1k 입력 토큰replace(19.4k)의 3.05배다. 성공률 격차(68% vs 85%)보다 토큰 격차가 훨씬 크다. 성공 1건당 비용으로 환산하면 patchreplace2.8배였고, 880회 전체 총지출($9.38)에서도 replace는 4개 툴 중 가장 적게 썼다.

전체로는 631회 성공(71.7%) 이었다.


5. 모델 × 툴 상호작용 매트릭스#

성공률(%) — 굵은 값은 해당 모델의 최고 툴:

모델apply_patchhashlinepatchreplace
deepseek-v4-flash909585100
qwen3.8-max258595
glm-5.245804595
kimi-k2.7-code65807090
hy375805590
kimi-k325908585
mimo-v2.585606060
mimo-v2.5-pro50806585
deepseek-v4-pro80808585
qwen3.7-plus75858070
minimax-m360653580

툴별 우승 횟수: replace 8, hashline 2, apply_patch 1, patch 0.

  • replace가 11개 중 8개 모델에서 최고 — 현대 LLM은 번호가 매겨진 read 출력만 있으면 절대 줄 번호 이해에 강하다. 오프셋 산수를 아예 제거해 버리는 게 핵심이다.
  • hashline은 kimi-k3(90%)와 qwen3.7-plus(85%)처럼 구조적 정밀도를 잘 따르는 모델에서 빛났다. 콘텐츠 해시 태그가 낡은 앵커 덮어쓰기를 원천 차단한다.
  • apply_patch는 mimo-v2.5 한 모델만 85%로 선호. 나머지 모델에선 hunk 헤더 산수 실패가 잦았다.
  • patch단 한 모델의 최고 툴도 되지 못했다.

6. 사례 연구: glm-5.2, 툴 하나로 50%p가 갈렸다#

같은 모델, 같은 20개 태스크에서 툴만 바꿨을 뿐인데:

replace : 95% (19/20) | 298,956 입력 토큰 | $0.3433
patch : 45% ( 9/20) | 1,481,206 입력 토큰 | $1.0886 (토큰 4.95배, 비용 3.2배)
apply_patch : 45% ( 9/20) | 1,482,332 입력 토큰 | $1.0882

replace로 바꾸자 성공률이 45% → 95%로 두 배가 되면서 토큰은 79.8% 감소했다. 툴 설계가 모델의 실제 코딩 능력보다 더 큰 변수인 경우가 있다는, 가장 극적인 증거다.


7. 왜 patch는 실패 루프에 빠지는가#

원본 이벤트 스트림(sample-failed-patch-loop-glm52.jsonl)을 보면 패턴이 반복적이다:

graph TD
A[patch 컨텍스트 매칭 실패] --> B[read로 파일 전체 재독]
B --> C[컨텍스트를 더 크게 붙인 patch 재시도]
C -->|여전히 공백/들여쓰기 미스매치| B
C -->|턴 한도 초과| D[실패 · 토큰 폭증]
  1. 미세한 공백 차이(탭 vs 스페이스, 줄바꿈, 들여쓰기)로 첫 매칭이 실패한다.
  2. 모델은 거의 예외 없이 파일 전체를 다시 읽어 재정렬한다.
  3. 더 큰 컨텍스트로 재시도하지만, 근본 원인(컨텍스트 오해)이 해결되지 않아 또 실패한다.
  4. 2~4턴 반복 후 턴 한도에 걸려 실패 — 태스크 하나에 75,000+ 토큰을 태운 사례도 있다.

반면 replace·hashline은 실패 시 “정확한 앵커 오류”라는 결정적 피드백을 주므로 모델이 즉시 재조준한다. 실패가 비싸지 않은 구조가 핵심이다. 퍼지 매칭은 컨텍스트 오해를 숨기고, 그 대가를 토큰으로 지불하게 만든다.


8. 하네스에 주는 교훈#

  1. 기본값은 replace로. 최신 프론티어·중간 모델에서 가장 높은 신뢰성, 가장 낮은 지연, 가장 적은 토큰 낭비.
  2. 대형 파일·동시 편집 환경에서는 hashline. 1,000줄 이상 파일에서 전체 블록 교체가 동시 편집을 덮어쓸 위험이 있다면, 콘텐츠 해시 태그가 낡은 앵커 문제를 제거한다.
  3. 순수 컨텍스트 diff patch는 피할 것. 컨텍스트 블록 형식에 특화 파인튜닝된 모델이 아니라면, 실패 루프가 컨텍스트 윈도우와 API 예산을 빠르게 소진한다.
  4. 성공률 단일 지표로 툴을 평가하지 말 것. 이 벤치마크처럼 성공률 2위인 툴이 비용은 최악일 수 있다. 성공 1건당 비용($/success)과 토큰 분포를 함께 봐야 한다.

9. 데이터 & 재현#

이 글의 모든 수치는 공개된 원본 데이터에서 직접 재계산했다. 벤치마크 데이터, 원본 이벤트 스트림, 재현 스크립트는 omp-bench-review 저장소에 포함돼 있다 (누구나 같은 인프라로 재현 가능):

  • data/summary-leaderboard.json — 44개 arm 전체 메트릭 (토큰 버킷, 가격, wall time)
  • data/model-rankings.csv — 스프레드시트용 테이블
  • data/raw-samples/ — 실제 JSONL 이벤트 스트림 3종 (완벽한 1턴 replace / patch 실패 루프 / 429 쿼터 오류)
  • scripts/analyze-results.ts · scripts/export-charts.ts — 리더보드·차트 재현 스크립트
Terminal window
bun run analyze # 리더보드 출력
bun run charts # ASCII 차트 출력

검증은 Docker 격리 verifier에서 tsc --noEmit + 숨은 동작 테스트로 수행했고, 실행 인프라는 Azure Spot(시간당 약 0.02달러 수준)의 일회성 VM으로 전체 캠페인 비용을 10달러 미만으로 유지했다.