빼기, 정렬, 증명: AI 에이전트가 리포지토리를 스파게티로 만드는 것을 막는 세 가지 스킬

Jul 1, 2026에 슈테판 모라비크에 의해 게시됨.
AI Agents Developer Productivity Agentic Workflows Code Review
이 페이지의 내용 9 분 읽기
  1. 1Part 1 · WHAT — 엔트로피가 기본값이다
  2. 2Part 2 · SO WHAT — PR 다섯 개, 각각 하나의 본능
  3. 3Part 3 · NOW WHAT

우리는 매일 코딩 에이전트에게 실제 티켓을 맡기고, 에이전트는 거의 항상 작동하는 무언가를 내놓습니다. 걱정거리는 그게 아니었습니다. 걱정은 어떻게 작업하느냐입니다. 이미 같은 일을 하는 세 개 옆에 새로 만든 헬퍼 하나, 호출자가 하나뿐인데 만들어 낸 새 추상화, 티켓이 지목한 경로 하나만 고치고 형제 경로 네 개는 깨진 채로 남기는 수정, 어느 쪽으로도 증거 없이 “아마 버그일 것"이라는 발견 사항. 각각의 변경은 국지적으로는 합리적입니다. 총합하면 엔트로피입니다.

TL;DR: 에이전트 오케스트레이션 코어에 대한 Tier-3 풀 리퀘스트 다섯 개에서, 조합 가능한 세 가지 스킬 — ponytail(빼기), grain(정렬), review-proof(증명) — 이 기능 다섯 개를 출시하면서 821줄을 제거했고, 그럴듯함만으로는 병합됐을 조용한 계약 위반을 잡아냈으며, 모든 변경이 기존 아키텍처의 결을 따라가게 했습니다. 각 스킬이 무엇을 하는지 실제 diff와 함께 소개합니다.

가드레일을 치우면 코딩 에이전트는 그럴듯해 보이는 부채를 매우 빠르게 찍어내는 기계입니다. 그래서 우리는 반대 방향으로 밀어 주는 세 가지 작은 스킬에 기댑니다 — 각각 하나의 본능: 빼기, 정렬, 증명.

  • ponytail — 실제로 작동하는 가장 게으른 것을 작성하라. 더하기 전에 삭제하라. (이건 우리가 만든 게 아닙니다 — 우리 스택에 맞게 각색한 Dietrich Gebert의 오픈 소스 스킬 입니다.)
  • grain / grain-review — 코드베이스가 이미 정해 둔 자리에 넣어라. 두 번째 방식을 발명하지 마라.
  • review-proof — 실패하는 테스트로 재현되기 전까지 발견 사항을 믿지 마라.

grain과 review-proof는 ponytail과 같은 정신으로, 우리 아키텍처에 맞춰 만들었습니다. 아래 다섯 개 PR은 모두 에이전트 오케스트레이션 코어 — 리포지토리에서 대충 하면 가장 비싼 대가를 치르는 단 한 곳 — 를 건드리고, 모두 Tier 3로 분류됩니다. 자동 리뷰어 위에 추가 테스트 커버리지와 사람 리뷰가 붙고, 예외는 없습니다.

세 가지 코딩 에이전트 스킬, 각각 하나의 본능: ponytail은 빼고, grain은 정렬하고, review-proof는 증명한다 — 각각이 없애는 것과 그 보상

한눈에 보는 세 스킬: ponytail은 빼고, grain은 정렬하고, review-proof는 증명한다.

Part 1 · WHAT — 엔트로피가 기본값이다

리포지토리를 AI 에이전트에게 넘길 때 아무도 경고해 주지 않는 것이 있습니다. 각 에이전트는 국지적으로 최적화하고 아무것도 기억하지 않습니다. 에이전트는 티켓을 볼 뿐, 팀이 몇 달에 걸쳐 수렴한 관례는 보지 못합니다. 기존 이메일 서비스를 두고 새로 만든 것을 선호할 이유가 없고, 리다이렉트 상태 집합이 이미 세 파일 건너에 정의되어 있다는 기억도 없고, “수정은 이 호출자가 아니라 공유 함수에 들어간다"는 본능도 없습니다. 그대로 돌려 두면 N개의 에이전트가 같은 일을 하는 조금씩 다른 N가지 방식을 만들어 냅니다. 이는 린트로 걸러낼 수 있는 코드 품질 문제가 아니라, 누적되는 구조적 드리프트입니다.

세 스킬은 각각 그 드리프트의 한 축을 겨냥합니다.

ponytail — 작동하는 가장 게으른 것

Ponytail은 새벽 3시에 남이 만든 영리한 추상화 때문에 호출을 받아 본 시니어 개발자이며, 다음 추상화를 작성하기를 거부합니다. 사다리를 한 칸씩 올라가며 버텨 주는 첫 번째 칸에서 멈춥니다: 이게 존재할 필요가 있나(YAGNI) → 이미 이 코드베이스에 있나 → 표준 라이브러리가 해 주나 → 네이티브 플랫폼 기능인가 → 이미 설치된 의존성인가 → 한 줄로 될까 → 그제서야 작동하는 최소한의 코드.

에이전트에게 가장 중요한 칸은 **“이미 이 코드베이스에 있나?”**입니다. 몇 파일 옆에 있는 것을 다시 구현하는 것이 에이전트 슬롭의 가장 흔한 형태입니다. 그리고 ponytail의 버그 수정 규칙은 diff를 정직하게 유지합니다: 증상이 아니라 근본 원인을 고쳐라. 건드리려는 함수의 모든 호출자를 grep 하세요. 공유 함수 안의 가드 하나가 호출자마다의 가드보다 작은 diff이고, 형제 경로들을 깨뜨리지도 않습니다.

grain / grain-review — 결을 따라가라

ponytail이 얼마나 적게 쓸지를 다스린다면, grain은 어디에 놓이고 어떤 모양을 취할지를 다스립니다. 규칙은 하나입니다: 가장 가까운 기존 예시를 찾고, 그 모양을 복사하고, 무엇을 복사했는지 밝혀라. 새 코드는 옆 파일을 쓴 사람이 이 파일도 쓴 것처럼 읽혀야 합니다.

grain은 아키텍처가 강제되는 곳이기도 합니다. 우리 백엔드는 비교적 표준적인 버티컬 슬라이스 + 헥사고날 구조입니다 — 프레젠테이션이 애플리케이션을 호출하고 애플리케이션이 도메인을 호출하며, 인프라는 안쪽을 향해 의존하고, 도메인은 절대 바깥으로 뻗지 않습니다. “이 라우트는 컨트롤러를 건너뛰고 서비스를 직접 끌어온다” 같은 발견 사항은 현학이 아닙니다 — 다음 달에 에이전트가 탐색할 수 있는 코드베이스와 그렇지 않은 코드베이스의 차이입니다. grain-review는 바로 이런 것들을 사냥합니다: 중복된 헬퍼, 넘어선 계층 경계, 다른 기능의 내부에 손을 뻗는 것, 이미 한 가지 방식으로 되어 있는 일에 대한 두 번째 관례.

review-proof — 발견 사항의 자격을 증명하라

일반적인 AI 코드 리뷰는 그럴듯한 발견 사항을 만들어 냅니다. 어떤 것은 진짜이고, 어떤 것은 자신만만한 헛소리이며, 밖에서 보면 똑같아 보입니다. review-proof는 자신을 믿지 않습니다: 리뷰한 뒤 모든 정확성 관련 발견 사항을 실제로 실패하는 테스트나 실행 가능한 재현으로 재현하도록 강제하고, 그렇지 못한 것은 버립니다. 마지막으로 구조 적합성을 위한 grain-review 패스를 수행합니다. 결과물은 각 항목이 실행 가능한 증거와 함께 오는 리뷰입니다 — 분위기가 아니라.

이게 통한다면 무엇을 봐야 하는가

  • H1 — 기능 PR에서 삭제가 나타난다. ponytail + grain이 작동한다면, 기능을 추가할 때 순 구조가 자주 줄어들어야 하며, 늘어나기만 해서는 안 됩니다.
  • H2 — 수정은 공유된 한 곳에 한 번만 들어간다. 근본 원인 수정은 여러 호출 지점을 하나의 가드로 접어 넣어야 하며, 호출자마다 가드를 뿌려서는 안 됩니다.
  • H3 — 리뷰가 사람이 흘려보내는 계약 위반을 잡는다. 증거 기반 리뷰는 “괜찮아 보인다"는 리뷰가 놓치는 버그 — 특히 조용한 종류 — 를 드러내야 합니다.

Part 2 · SO WHAT — PR 다섯 개, 각각 하나의 본능

우리 에이전트 코어에 대한 다섯 개의 실제 변경입니다. 내부는 의도적으로 모호하게 유지합니다 — 리포지토리는 비공개입니다 — 하지만 숫자는 실제 diff에서 계산했고, 교훈이 이식 가능한 부분입니다.

빼기: 열두 개 fetch 지점을 위한 가드 하나

한 흐름 단계 제품군이 사용자가 제공한 URL을 DNS 확인 안전 검사 없이 가져왔고, 그래서 내부 주소로 해석되는 호스트 이름이 백엔드에서 클라우드 메타데이터에 도달할 수 있었습니다. 유혹적인 수정은 열두 개가 넘는 fetch 지점마다 검사를 추가하는 것입니다. Ponytail의 답은 반대였습니다: 모든 곳에서 쓰이는 하나의 공유 가드 fetch 헬퍼 — 그리고 와일드카드 DNS 트릭이 그냥 지나쳐 버린 직접 만든 사설 네트워크 테이블, 중복된 리다이렉트 루프 세 개, 여러 파일에 복사-붙여넣기된 네트워크 검사를 삭제했습니다.

그 diff는 공유 헬퍼를 추가하고 22개 파일에 걸친 약 90줄의 중복을 제거했습니다. 그 삭제가 바로 이 이야기의 핵심입니다: 이것이 H2의 실체입니다 — 근본 원인 수정이 티켓이 지목한 한 경로를 패치하는 대신 모든 호출자를 하나의 가드로 통과시켰습니다.

열두 개가 넘는 사용자 URL fetch 지점이 각자 우회 가능한 검사를 갖고 하나의 공유 가드 fetch 헬퍼로 모여든다

근본 원인 수정: 열두 개의 즉흥적 fetch 지점이 하나의 공유 가드 헬퍼로 접힌다. 게으른 수정과 안전한 수정은 같은 수정이다.

빼기 + 증명: 셰이프 가드 하나, 실제 런타임에서 증명

우리 워커 런타임은 실행 결과를 직렬화된 문자열로 저장하는데, 때로는 단일 요소 리스트로 감쌉니다. 평범한 객체를 기대한 소비자들은 여기서 크래시했습니다. 잘못된 수정은 소비자마다 방어적 타입 검사를 흩뿌리는 것입니다. 대신: 작은 셰이프 정규화 헬퍼 하나를 만들고 모든 소비자를 그것으로 다시 겨냥했습니다 — 규율 없는 에이전트가 작성했을 N개의 즉흥적 가드를 대체하는 하나의 가드를 거의 순수하게 추가한 것입니다(+558 / −24, 7개 파일).

이것을 review-proof 이야기로 만드는 부분은 테스트입니다. 가정한 직렬화 형태에 대해 단언하는 대신, 실제 런타임과 스토리지를 통해 진짜 워크플로를 실행하고 — 목 없이 — 런타임이 실제로 저장하는 형태를 증명했습니다. 티켓의 열린 질문은 말 그대로 *런타임이 여기서 무엇을 직렬화하는가?*였고, 정직한 답은 실행해 볼 수 있는 것뿐입니다.

증명: 리뷰가 조용한 계약 위반을 잡아냈다

기능: 노드별 폴백 모델로, 한 제공자에 고정된 흐름이 장애 중에도 우아하게 성능을 낮추도록 합니다. 당연한 첫 시도는 프레임워크 내장 폴백 컴비네이터로 모델을 감싸는 것이었습니다.

해피 패스에서는 작동했습니다. 하지만 isinstance를 통해 구체적 모델 타입에 게이트가 걸린 두 가지 제공자 기능을 조용히 꺼 버렸습니다 — 감싼 객체는 더 이상 그 타입이 아니므로 네이티브 구조화 출력과 프롬프트 캐싱이 둘 다 조용히 꺼졌습니다. 오류도 없고, 해피 패스 테스트 실패도 없었습니다. 사람 리뷰가 흘려보내고 “괜찮아 보인다"는 에이전트가 승인하는 바로 그런 종류입니다.

review-proof는 승인하지 않았습니다 — 두 위반을 모두 실패하는 테스트로 재현했고, 그 결과 설계가 바뀌었습니다: 실행 시점에 더 아래에서 폴백을 적용해 모든 모델이 구체적 타입을 유지하고 타입 게이트 기능이 계속 작동하도록 했습니다. H3가 결정적으로 확인되었습니다: 그럴듯함은 배포했을 버그를 증명이 잡았습니다.

정렬: 피커 하나, 두 개의 사본이 아니라

두 번째 알림 채널을 추가하자 채널 피커 UI에 두 개의 집이 생겼습니다 — 생성 마법사와 설정 모달. 기본적인 에이전트 행동은 두 곳 모두에 새 분기를 추가해 같은 상태 머신의 사본을 두 개로 늘리는 것입니다. grain은 이렇게 말했습니다: 이것이 취해야 할 모양은 이미 하나로 정해져 있다 — 공유되게 만들어라. 단일 피커 훅을 추출해 두 화면 모두를 그 훅으로 구동하고, 새 채널을 기존 설정 유니언에 끼워 넣고, 새 전송 기계를 추가하는 대신 기존 이메일 서비스를 재사용했습니다.

24개 파일에 걸쳐 +1,735 / −340. 이 정도 규모의 기능이 340줄을 제거하는 것은 가시화된 H1입니다: 피커 사본 두 개를 하나로 중복 제거한 것이 새 채널 비용의 상당 부분을 지불했습니다.

정렬 + 증명: 엔드포인트를 재사용하고 경로를 그대로 따른다

이슈 생성 시 사용자가 파일을 첨부할 수 있게 하려면 새 업로드 엔드포인트, 새 디스패치 메커니즘, 새 프롬프트 경로가 필요할 수도 있었습니다. grain은 그 거의 전부를 기존 레일 위로 보냈습니다: 기존 업로드 엔드포인트, 백엔드 화이트리스트를 정확히 그대로 비추는 프런트엔드 허용 목록, 그리고 예약된 작업이 이미 사용하던 적격성 메커니즘을 재사용한 지연 디스패치 수정입니다. 증거 기반 수정과 함께 출시되었고, 병렬 업로드 시 데이터를 잃었을 실제 트랜잭션 격리 버그도 포함되어 있었습니다. 27개 파일에 걸쳐 +1,776 / −218 — 새 슬라이스를 발명하는 대신 기존 슬라이스에 합류해 218줄을 제거할 방법을 여전히 찾아낸 큰 기능입니다.

스코어보드

PR별 추가 및 제거 줄 수와 각 PR을 만든 본능(빼기, 정렬, 증명)을 보여주는 다섯 개 Tier-3 PR의 스코어보드

다섯 개의 Tier-3 PR: 각각이 추가한 것, 제거한 것, 그리고 그 뒤에 있는 본능.

에이전트 코어에 대한 다섯 개의 기능 및 수정 PR이 821줄을 제거했습니다 — 더 적게 해서가 아니라, 이미 존재하는 것을 복제하지 않고 근본 원인 수정으로 불필요해진 증상 패치를 남기지 않음으로써.

전체 공개

  • 이것은 스킬이지 연구가 아닙니다. 기준선 군이 있는 통제 실험이 아니라, 규율이 적용된 다섯 개의 실제 PR입니다. 반사실 — 같은 에이전트가 스킬 없이 배포했을 것 — 은 측정이 아니라 정보에 근거한 추정입니다. 조용한 계약 위반 이야기가 가장 깨끗한 증거입니다. 재설계 전에 리뷰가 버그를 재현하는 것을 지켜봤기 때문입니다.
  • 줄 수는 대리 지표입니다. −821은 diff에서 나온 실제 숫자이지만, “제거된 줄"은 “회피한 중복과 죽은 유연성"을 대신합니다. 에이전트가 추측성 200줄을 쓰지 않도록 설득한 스킬은 diff에 아무 흔적도 남기지 않습니다 — 가장 큰 성과는 여기서 보이지 않습니다.
  • 토큰 절감은 방향성입니다. 더 작은 diff, 더 적게 건드린 파일, 재사용된 구조는 생성·리뷰·재리뷰에 쓰는 토큰을 줄여 주지만, PR별 토큰 차이를 확정 수치로 제시하지는 않습니다.
  • ponytail은 우리 것이 아닙니다. Dietrich Gebert의 오픈 소스 스킬 이고 우리가 각색했습니다. grain과 review-proof는 같은 정신으로 만든 우리 것입니다. 세 가지 모두 Claude Code에서 로컬 프로젝트 스킬로 실행됩니다 — 설치하는 바이너리가 아니라 프롬프트와 절차입니다.
FlowHunt 로고

비즈니스 성장 준비가 되셨나요?

오늘 무료 평가판을 시작하고 며칠 내로 결과를 확인하세요.

Part 3 · NOW WHAT

출시된 것. 조합 가능한 세 가지 스킬. ponytail과 grain은 작성하는 동안 실행되고, ponytail-review, grain-review, review-proof는 diff에 대해 실행됩니다. review-proof는 마지막 단계로 grain-review를 연결하므로, 한 번의 증명된 리뷰가 구조 점검까지 덤으로 받습니다.

월요일에 할 수 있는 것 — 우리 스킬과 똑같을 필요는 없습니다:

  1. “재사용"을 열 번째 칸이 아니라 두 번째 칸으로 만들어라. 에이전트가 헬퍼를 작성하기 전에, 존재하는 헬퍼를 grep 하게 하라. “이미 이 코드베이스에 있나?“는 “깔끔하게 작성할 수 있나?” 위에 있어야 한다.
  2. 근본에서 고치고 호출자 목록으로 증명하라. 모든 버그 수정이 건드린 함수의 모든 호출자를 밝히도록 요구하라. 공유 함수의 가드 하나가 호출자마다의 가드보다 낫고, diff도 더 작다.
  3. 새 코드에 복사할 가장 가까운 형제를 줘라. “가장 가까운 기존 예시를 찾아 그 모양을 그대로 따르라"는 아키텍처를 아무도 읽지 않는 문서에서 에이전트가 따르는 기본값으로 바꾼다.
  4. 계층 경계는 분위기가 아니라 CI에서 강제하라. 새로운 교차 계층 임포트에만 실패하는 래칫을 쓰면 기존 부채의 바다를 끓이지 않고도 선을 지킬 수 있다.
  5. 재현할 수 없는 발견 사항은 배포하지 마라. 에이전트가 먼저 실패하는 테스트를 쓰게 하라. 버그를 재현시키지 못한다면 그것은 버그가 아니라 의견이다. 버려라.
  6. 리뷰가 삭제하게 하라. 리뷰 패스를 정확성과 별개로 과잉 엔지니어링 — “무엇을 잘라낼 수 있나” — 에 겨냥하라. diff의 최고 결과는 더 짧아지는 것이다.

시도해 보세요, 특히 당신에게 실패한다면. 실제 코드베이스에서 코딩 에이전트를 돌린다면 엔트로피는 이미 일어나고 있습니다 — 측정하지 않았을 뿐입니다. 이 중 하나를 다음 열 개의 에이전트 PR에 대한 리뷰 패스로 바꿔서 삭제된 줄을 세어 보세요. 빼기-정렬-증명이 diff를 줄이지 못하거나 조용한 위반을 잡지 못한다면, 정말 듣고 싶습니다. 정정과 반례는 특히 환영합니다.

에이전트는 더한다. 일은 에이전트가 모든 줄의 자격을 증명하게 만드는 것이다.

자주 묻는 질문

슈테판은 FlowHunt를 구축하는 AI 및 소프트웨어 엔지니어입니다. 제품 자체를 넘어, 개발자를 위한 에이전트 소프트웨어 엔지니어링 워크플로우를 설계하여 개발 비용을 절감하면서 코드 품질을 향상시킵니다.

슈테판 모라비크
슈테판 모라비크
AI 및 소프트웨어 엔지니어

스스로 값을 하는 에이전트 워크플로 만들기

FlowHunt는 개발 비용을 줄이면서 코드 품질을 높이는 에이전틱 워크플로와 리뷰 게이트, MCP 통합을 엔지니어링 팀이 설계하도록 돕습니다.