복구가 아닌 예방: AI 코딩 에이전트를 제어하는 도구를 만들며 배운 것들
요약
AI 코딩 에이전트가 생성하는 불필요한 코드(Slop)를 방지하기 위한 Claude Code 플러그인 'slopstop'을 소개합니다. 구현 전 실패하는 테스트를 먼저 작성하고 명확한 완료 정의를 설정하여, 사후 복구가 아닌 사전 예방 중심의 개발 워크플로우를 제안합니다.
핵심 포인트
- AI 에이전트의 '프롬프트 후 기도하기' 루프를 예방 중심 루프로 전환
- 구현 전 티켓 기반의 실패하는 테스트(Failing tests) 선행 작성
- 명문화된 완료 정의(DoD)를 통한 구현 범위 이탈 방지
- 커밋 전 단순화 단계(Simplify pass)를 통한 과잉 엔지니어링 제거
AI가 생성한 버그가 발생했나요? Diff(차이점)에 Slop(불필요한 코드)이 가득한가요? 당신만 그런 것이 아닙니다.
slopstop은 '프롬프트 입력 후 기도하기(prompt-and-hope)' 루프를 예방 중심의 루프로 대체하는 Claude Code 플러그인입니다. 작업은 구현이 존재하기 전, 범위가 지정되고 테스트가 고정된 티켓(Ticket)에서부터 시작됩니다. 여러 번의 독립적인 검토를 통해 Slop을 찾아내기 전까지는 머지(Merge)되지 않습니다. 핵심 전략은 '예방이 복구보다 저렴하다'는 것입니다.
Slop을 검토하여 제거하는 방식의 문제점
AI가 작성한 코드와 관련된 대부분의 도구는 복구(Recovery) 도구입니다. 이미 존재하는 Diff를 살펴보고 무엇이 잘못되었는지 찾아내는 방식입니다. 이는 유용하며, slopstop 또한 이러한 유형의 도구들을 사용하지만, 다양한 다른 분석 및 적대적 에이전트(Adversarial agents)와 결합하여 사용합니다. slopstop가 코드 리뷰 도구를 호출할 때쯤이면, 새로운 추상화(Abstractions) 추가, 범위를 벗어난 구현, 또는 공허한 테스트(Vacuous testing)와 같이 정말 비용이 많이 드는 실수들은 이미 예방되어 있어야 합니다.
리뷰 도구들은 코드 작성 에이전트에게 이용당할 수 있으며, 실제로 이용당하고 있습니다. 에이전트가 (테스트를 포함한) 작동하는 프로그램을 남겨두지만, 그 형태는 에이전트가 선택한 방식이기 때문입니다. 달리 말하면, 코드 리뷰 에이전트가 "이걸 전부 버리고 더 간단하게 만드세요"라고 말하는 것을 본 적이 있습니까?
테스트가 통과하는 경우가 흥미로운 사례입니다. AI가 생성한 테스트의 흔하고 슬픈 실패 모드는 구현 내용으로부터 역공학(Reverse-engineered)된다는 점입니다. 즉, 에이전트가 방금 작성한 코드를 읽고 그것을 설명하는 단언(Assertions)을 작성하는 것입니다. 이러한 테스트는 버그를 포함하여 현재의 동작을 고정하며, 공허하게 영원히 통과됩니다. 리뷰 단계에서는 이를 잡아낼 수 없습니다. 테스트는 통과(Green) 상태이고, Diff는 깨끗하지만, 코드는 잘못되어 있습니다.
slopstop가 대신 하는 일
노력의 단계를 더 앞당깁니다 — 구현이 존재하기 전 단계로 말입니다.
티켓이 요구하는 사항에 대한 실패하는 테스트 (Failing tests). /slopstop:plan은 기존 코드가 아닌 티켓에 명시된 동작을 바탕으로 테스트를 먼저 작성합니다. 구현이 시작되기 전에 이 테스트들은 반드시 실패(red) 상태여야 하며, 올바른 이유로 실패해야 합니다. 계획 내의 모든 작업 항목은 이름이 지정된 테스트가 통과(green)되는 것에 고정됩니다. slopstop은 구현 작업이 시작되기 전, 구현체 없이 실패하는 테스트만 있는 상태를 커밋합니다.
명문화된 완료 정의 (Definition of Done) 및 범위 경계 (scope boundary). 이 또한 티켓에 평이한 언어로 사전에 초안이 작성됩니다. Claude가 조용히 diff(차이점)를 넓히는 대신, "이 범위 외 작업(out-of-scope task)을 위해 새 티켓을 생성할까요?"라고 묻고 멈춘다면, 이 기능이 제대로 작동하고 있음을 알 수 있습니다. slopstop 티켓의 완료 정의(definition of done) 섹션은 티켓의 구현 사항이 머지(merge)될 수 있는 유일한 방법입니다: "모든 완료 정의 조건이 충족되었는가?"
커밋이 존재하기 전의 단순화 단계 (A simplify pass). /slopstop:pr은 커밋되지 않은 변경 사항에 대해 단순화 단계(simplify pass)를 실행합니다. 즉, 이를 제거하는 비용이 여전히 '무료'인 시점에 과잉 엔지니어링 (over-engineering), 데드 코드 (dead code), 불필요한 추상화 (needless abstraction) 등을 처리합니다. 이를 위해 우리는 Claude 자체의 단순화 단계 (Claude's own simplify pass)를 사용합니다 (버그를 찾지 않고 수정 사항만 적용하는 정리 전용 리뷰). 따라서 이는 하나의 "리뷰 유형 (review type)" 단계입니다.
단순화 단계가 놓치는 것을 잡아내는 복잡도 게이트 (complexity gate). slopstop은 lizard를 사용하여 diff 내의 모든 함수에 대해 순환 복잡도 (cyclomatic complexity)를 계산하며, 설치되어 있지 않다면 자동으로 설치해 줍니다. 복잡도가 10을 넘으면 경고를 보내고, 15를 넘으면 실패 처리합니다. 이는 특정 AI 실패 모드를 잡아냅니다. 즉, 에이전트가 문제를 작은 조각으로 분해하는 대신, 수십 개의 분기문(branch)을 가진 하나의 함수에 모든 것을 밀어 넣는 경우를 잡아냅니다. 인간 리뷰어는 테스트가 통과된다는 이유로 이를 그냥 지나칠 수 있지만, 복잡도 게이트는 허용하지 않습니다.
스스로를 검증하는 리뷰 단계. 모든 티켓(ticket)의 구현에 대해 자동화된 코드 리뷰 (code review)가 수행됩니다. slopstop는 코드 리뷰에서 보고된 각 발견 사항(finding)을 검증하며, 검증 가능한 항목들을 '수정 필수(should-fix) / 수정 권장(could-fix) / 건너뜀(skip)'으로 분류합니다. 코드와 대조했을 때 타당하지 않은 발견 사항은 의무적으로 적용되는 대신, 서면으로 반박됩니다.
단일 티켓을 넘어 확장 가능함
슬롭(slop)을 방지하는 것이 혼자 일해야 함을 의미하지는 않습니다. /slopstop:design은 당신이 보낸 아이디어나 단순한 생각들에 대해, 당신이 무엇을 원하는지 그리고 그것을 어떻게 수행하고 싶은지가 충분히 명확해질 때까지 인터뷰를 진행합니다. 이를 통해 제품 요구 사항 문서 (Product Requirements Document, PRD)와 해당 아이디어를 위한 헌장 (Charter)을 작성할 수 있습니다.
/slopstop:tickets는 PRD와 헌장으로부터 티켓 트리 (ticket tree)를 잘라내어, 이를 무너뜨리려는 적대자 (adversary)에게 전달합니다. 이 적대자는 생성된 모든 티켓을 /slopstop:design에 의해 생성된 PRD 및 헌장과 대조하며, 일치하지 않는 사항을 발견하면 이유와 함께 티켓 트리를 거부합니다.
/slopstop:run은 여러 모델 계층 (model tiers)에 걸쳐, 각 티켓당 하나씩 자신의 git 워크트리 (git worktree)에 격리된 병렬 헤드리스 에이전트 (headless agents)들을 구동합니다. 여기서 각 계층의 작업은 바로 위 계층에 의해 검증됩니다. 성능이 낮은 모델은 비용이 적게 들지만 더 많은 수정 단계를 유발하며, 이는 전형적인 '비용과 시간의 트레이드오프 (money-for-time trade)' 관계를 보여줍니다.
단일 티켓에 적용되는 보장 사항은 전체 플릿 (fleet)에도 동일하게 적용됩니다: 변조 검사 (tamper checks)가 포함된 고정된 테스트, 브랜치가 통합되기 전의 독립적인 인계 검증 (handoff verification), 그리고 모든 단계 경계에서의 인간 게이트 (human gate)가 이에 해당합니다.
무언가를 잡아냈을 때의 모습
적대적 검증 (adversarial verification)에 대한 주장은 흔하므로, 트랜스크립트 (transcript)를 제공합니다. 실제 실행 사례: 다섯 문장의 기능 설명이 의도적으로 성능을 낮춘 에이전트 플릿에 의해 7개의 병합된 PR (merged PRs)로 변환되는 과정을 시간 순서대로 보여주며, 프로세스가 무언가를 잡아낸 모든 지점에서 트랜스크립트를 인용합니다.
포착된 사례들 중에는 다음과 같은 것들이 있습니다: 70초 간격으로 이루어진 두 사람의 답변 사이에서 모순을 발견한 디자인 인터뷰(design interview). 지정된 락(lock)이 실제로 작동하지 않을 것이라는 이유로 티켓 트리(ticket tree)를 거부하고, 40번의 실험을 통해 이를 증명한 적대적 에이전트(adversary). 성공을 보고하고 녹색 트리(green tree)와 함께 깔끔하게 종료되었으나, 실제로는 아무것도 수행하지 않은 구현 에이전트(implementing agent). 그리고 마지막으로, 테스트 스위트(suite)를 재실행하여 코드가 정확함을 확인한 뒤, 오케스트레이터(orchestrator) 자신의 보고서가 자체 에이전트 중 하나에 대해 위반 사항을 조작했음을 발견한 적대적 에이전트 — 이후 티켓에 공개적인 철회(retraction)가 이어졌습니다.
마지막 사례는 깊이 생각할 만한 가치가 있습니다. 프로세스가 자신의 감독자(supervisor)가 거짓말을 하고 있다는 사실을 잡아낸 것입니다.
시도해 보기
워크스루(walkthrough)는 slopstop이 코드 오류를 잡아내고, 티켓 문제를 포착하며, 무엇보다도 _인간의 디자인 오류(human design errors)_를 잡아내는 수많은 사례를 보여줍니다. 전체 내용을 읽어볼 가치가 있습니다.
slopstop 설치:
/plugin marketplace add iansmith/slopstop
/plugin install slopstop@slopstop
그 다음 티켓부터 시작하세요:
/slopstop:start <ticket>.
GitHub: github.com/iansmith/slopstop
접근 방식이나 적대적 에이전트의 포착 사례에 대해 질문이 있으신가요? 댓글에서 기다리겠습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기