Skip to content
게으른 엔지니어의 기술 블로그
Go back

MCP 서버랑 스킬 리뷰 2편 — ponytail이 redundant하다는 판단은 틀렸다

지난 글에서 ponytail(코드를 쓰기 전에 재사용·표준 라이브러리·네이티브 기능 순으로 먼저 확인하게 하는 미니멀리즘 규칙)을 Hermes에만 설치하고, Claude Code에겐 “이미 겹치는 지침이 있다”는 이유로 설치하지 않았다. 그런데 이 판단에 구멍이 있었다.

”성능 비교가 Claude Code로 한 거 아니야?”

글을 다 쓰고 나서 이상한 생각이 하나 들었다.

Skill을 소개하는 유튜브는 기본적으로 Claude Code에 붙이는 스킬을 소개하는 건데, 시스템에 이미 있는 건데, Ponytail 같은건 왜 만들었으며, 성능 비교가 Claude Code와 한게 아닌가?

정확한 지적이었다. ponytail의 벤치마크 자체가 “실제 Claude Code 세션으로, FastAPI+React 리포를 편집시켜 Haiku 4.5로 측정”한 결과였다. no-skill 베이스라인도 당연히 Claude Code의 기본 시스템 프롬프트를 그대로 쓴 상태였을 텐데, 그 상태에서도 ponytail을 붙이니 코드량 -54% 같은 차이가 났다는 거다. 그렇다면 “시스템 프롬프트에 이미 비슷한 지침이 있으니 한계효용이 낮다”는 판단은 근거가 약했다 — 지침이 존재한다는 것과 그 지침이 실제로 잘 지켜진다는 것을 같은 걸로 취급한 셈이었다.

이건 사실 이날 Honcho 실험에서 이미 한 번 배운 교훈이었다. low 티어가 가끔 틀렸던 것도 모델이 부족해서가 아니라 반복 횟수 예산이 부족해서였다 — 기능이 있다는 것과 그게 실제로 효과적으로 발휘되는 것은 다른 문제였다. 시스템 프롬프트에 지침이 텍스트로 박혀있어도, 매 턴 얼마나 엄격하게 지키는지는 별개일 수 있다는 걸 놓치고 있었다.

직접 A/B 테스트해보기

말로 재반박하는 대신 직접 확인하기로 했다. 같은 코딩 과제를 두 조건으로 나눠서 풀게 했다 — 하나는 그냥, 하나는 ponytail의 사다리 규칙을 프롬프트에 그대로 넣고. 매번 새로 띄운 에이전트로 돌려서, 지금까지의 대화 맥락에 물들지 않은 “블라인드” 상태를 유지했다.

과제는 여섯 개였다. 일부러 성격을 다르게 잡았다 — 정답이 사실상 하나뿐인 과제(문자열 검증, 깊은 복사, 중복 체크)와, 구현 방식에 여러 선택지가 있는 과제(디바운스, ID 생성, 재시도 로직)를 섞었다.

과제baselineponytail차이
나이 문자열 검증6줄5줄거의 없음
검색창 디바운스(300ms)~20줄 (IIFE, var, 상수 분리, 방어적 null 체크, 심지어 이미 있다는 fetchResults까지 재정의)~10줄뚜렷함
객체 깊은 복사3줄 (JSON.parse(JSON.stringify(...)))3줄 (동일)없음
고유 ID 생성핵심은 3줄인데 CommonJS/ESM/global 세 가지 변형을 다 보여줌3줄, 답 하나만약간 있음
배열 중복 체크3줄 (Set 한 줄)3줄 (동일)없음
fetch 3회 재시도17줄 (maxAttempts/lastError 변수 분리)11줄있음 (~35% 감소)

패턴이 뚜렷했다. 정답이 하나뿐인 세 과제(나이 검증, 깊은 복사, 중복 체크)는 baseline도 이미 최소 구현이라 ponytail이 낄 자리가 없었다. 반면 구현 방식에 선택지가 있던 세 과제(디바운스, ID 생성, 재시도)에서는 매번 ponytail 쪽이 실제로 코드를 줄이거나, 불필요한 방어 코드를 뺐거나, 심지어 이미 존재한다고 명시된 함수를 다시 정의하는 실수를 피했다.

디바운스 과제가 제일 인상적이었다. baseline은 IIFE로 감싸고 DEBOUNCE_DELAY 상수를 따로 빼고 clearTimeout 전에 null 체크까지 넣었는데, 문제 설명에 “이미 있다”고 명시한 fetchResults를 placeholder로 다시 정의해버렸다 — 실수로 진짜 구현을 가릴 뻔한 코드였다. ponytail 쪽은 clearTimeout(undefined)가 안전한 네이티브 동작이라는 걸 알고 null 체크를 생략했고, “이미 존재한다”는 사다리 2번 규칙을 정확히 지켜서 fetchResults를 건드리지 않았다.

결론과 설치

ponytail 자신의 벤치마크가 설명한 패턴(“이미 최소화된 코드엔 거의 0, 과잉 설계 함정이 있는 곳에서만 크게”)이 Sonnet 5로 돌리는 Claude Code에서도 그대로 재현됐다. 실제 업무 코드는 대부분 “정답이 하나뿐인” 종류보다 “구현 선택지가 여러 개인” 종류에 가까우니, 처음 판단(“redundant하다”)은 뒤집혔다.

claude plugin marketplace add DietrichGebert/ponytail
claude plugin install ponytail@ponytail

설치는 CLI로 바로 됐다(scope: user). Hermes 때처럼 게이트웨이 재시작 같은 절차는 없지만, 지금 켜져 있는 세션에 바로 반영되는지는 확실치 않아서 다음 세션부터 제대로 체감될 걸로 본다.

처음 낸 결론에서 멈췄다면 “이미 지침이 있다”는 말만 믿고 넘어갔을 거다. 질문 하나가 그 결론을 다시 열어봤고, 실제로 재보니 절반은 틀린 판단이었다.


Share this post:

Previous Part
MCP 서버랑 스킬 7개를 리뷰한 하루 — 설치한 건 하나뿐이었다
Next Part
기능 하나 만드는데 대화·스펙·플랜·서브에이전트를 거쳤다