본문으로 건너뛰기

© 2026 Molayo

Zenn헤드라인2026. 05. 22. 23:03

추측→변경→다시 고장남: 코딩 에이전트의 악순환에 /tdd와 /diagnose 삽입하기

요약

AI 코딩 에이전트가 추측만으로 코드를 수정하다 발생하는 악순환을 방지하기 위한 전략을 다룹니다. /tdd와 /diagnose 스킬을 활용하여 에이전트에게 명확한 pass/fail 판정 기준과 확인 루프를 제공하는 방법을 설명합니다.

핵심 포인트

  • 에이전트의 추측 기반 수정을 방지하기 위한 확인 루프 설계 필요
  • /tdd 스킬을 통한 테스트 주도 개발(TDD) 방식의 에이전트 워크플로우 적용
  • /diagnose 스킬을 활용하여 고장 난 동작에 대한 추적 및 검증 절차 삽입
  • 에이전트에게 명확한 pass/fail 신호를 제공하여 작업 정확도 향상

고쳤을 텐데, 또 고장난다

AI 코딩 에이전트(AI coding agent)에게 "이 버그를 고쳐줘"라고 부탁한다.

몇 분 후, 에이전트는 "수정했습니다"라고 답한다.

실행해 보면 고쳐져 있지 않다. 다른 부분이 고장 나 있는 경우도 있다.

다시 전달한다.

에이전트는 코드를 읽고, 원인을 추측하고, 변경을 가한다.

그리고, 또 고장 난다.

이 흐름에서는 변경이 올바른지 판단할 재료가 부족하다.

인간 엔지니어는 변경할 때마다 실행해서 확인한다.

테스트를 돌린다. 로그를 본다. CLI를 입력한다. 화면으로 확인한다.

에이전트에게도 동일한 확인을 시킬 필요가 있다.

그 확인 절차를 매번 프롬프트(Prompt)에 상세히 적는 것은 번거롭다.

그래서 사용할 수 있는 것이 에이전트에게 작업 절차를 전달하는 스킬 (Skill) 이다.

이 기사에서는 구현 중에 사용하는 /tdd와, 고장 난 동작을 추적할 때 사용하는 /diagnose를 다룬다.

둘 다 에이전트가 추측으로 진행하기 쉬운 곳에 pass/fail 판정 기준을 삽입하기 위한 절차이다.

에이전트 스킬이란

Claude Code 등과 같은 AI 코딩 에이전트 (AI coding agent) 는 지시에 따라 코드를 쓰거나 디버깅을 할 수 있다.

아무것도 설정하지 않으면 작업 절차는 에이전트에게 맡겨진다.

mattpocock/skills 는 그 절차를 전달하는 작은 파일들의 모음이다.

/tdd/diagnose와 같은 명령어를 입력하면, 에이전트가 대응하는 스킬 파일을 읽어 들여 정해진 절차로 작업한다.

/tdd는 앞으로 만들 기능에 판정 기준을 둔다.

/diagnose는 이미 고장 난 동작에 확인 수단을 둔다.

에이전트의 작업을 모두 구속하는 것이 아니라, 실패하기 쉬운 장면에 확인 루프(Confirmation loop)를 추가하는 설계이다.

문제의 구조: 에이전트에게 pass/fail 신호가 없다

LLM 에이전트에게 디버깅을 맡기면 흔히 다음과 같이 된다.

  • "이 버그를 고쳐줘"라고 전달한다
  • 에이전트가 코드를 읽고 추측한다
  • 변경을 가하고 "고쳤습니다"라고 말한다
  • 작동하지 않는다. 다시 전달한다
  • 2~4를 반복한다

"고쳐줘"라고만 전달하면 에이전트는 수정안을 내놓는 방향으로 나아간다.

그 수정이 올바른지 확인하는 공정은 지시하지 않으면 누락될 수 있다.

"이 판정 기준을 만족하도록 고쳐줘"라고 전달하면 에이전트는 확인하면서 진행할 수 있다.

/tdd/diagnose가 삽입하는 것은 바로 이 확인 단계이다.

/tdd가 삽입하는 것

TDD (Test-Driven Development, 테스트 주도 개발)에서는 RED/GREEN/REFACTOR라는 흐름으로 작게 진행한다.

실패하는 테스트를 쓰고, 그 테스트를 통과시키고, 필요하다면 구현을 다듬는 순서이다.

이 기사에서 다루는 /tdd의 사용법도 이 사고방식을 에이전트용으로 사용한다.

큰 사양을 한꺼번에 전달하는 것이 아니라, 하나의 동작을 테스트로 나타내고 하나를 구현하는 작은 루프로 나눈다.

에이전트에게 효과적인 것은 테스트를 쓰는 것뿐만이 아니다.

순서도 효과가 있다.

먼저 실패하는 테스트를 쓴다.

그 테스트가 실패하는 것을 확인한다.

거기서부터 구현한다.

마지막으로 테스트가 통과하는 것을 확인하고, 필요하다면 리팩터링 (Refactoring)을 한다.

이 순서를 지키면 에이전트는 "무엇을 만족해야 하는가"를 놓치기 어려워진다.

RED/GREEN이란

TDD에서는 테스트 상태를 두 가지 색으로 나타낸다.

  • RED: 테스트가 실패하고 있다. 구현이 아직 존재하지 않거나, 테스트가 나타내는 동작을 만족하지 못하고 있다.
  • GREEN: 테스트가 통과하고 있다. 적어도 그 테스트가 나타내는 동작은 만족하고 있다.

/tdd는 우선 RED부터 시작한다.

"현재 구현으로 이 테스트가 실패한다"는 것을 확인한 뒤에 구현에 들어간다.

에이전트는 현재 코드의 상태를 기준으로 작업할 수 있다.

처음부터 구현으로 뛰어넘지 않고, 먼저 실패하는 판정 기준을 만든다.

모든 테스트를 먼저 쓰게 하면 어떤 일이 일어나는가

"모든 테스트를 먼저 쓰고 구현해줘"라고 지시하면, 존재하지 않는 함수의 사양을 상상해서 테스트를 쓰는 경우가 있다.

그 후 자신이 쓴 테스트에 맞는 구현을 만든다.

테스트는 통과한다.

하지만 그것이 정말로 필요한 동작인지는 별개의 문제다.

하나씩 진행하면 각 테스트가 동작 확인을 거친 사양으로서 쌓여 올라간다.

  • 먼저 하나를 실패시킨다
  • 그 하나를 통과시킨다
  • 필요하다면 구현을 정돈한다
  • 다음 하나로 넘어간다

이 작은 루프가 에이전트의 추측을 억제합니다.

외부에서 보이는 동작을 테스트한다

코드에는 사용자나 다른 모듈에서 보이는 입구와, 내부에서만 사용하는 처리가 있습니다.

외부에서 호출할 수 있는 계약이나 입구를 public interface (공개 인터페이스)라고 부릅니다.

내부 보조 함수나 private method (개별 메서드)는 구현의 상세 내용입니다.

private method의 테스트를 작성하면, 내부 구현을 바꿀 때마다 테스트가 깨집니다.

리팩터링 (Refactoring)을 할 때마다 테스트도 다시 작성해야 합니다.

public interface에 대한 테스트는 "무엇을 받아서 무엇을 반환하는가"라는 계약을 검증합니다.

내부 구현을 바꾸더라도 입출력이 같다면 테스트는 깨지지 않습니다.

에이전트도 구현의 형태가 아니라, 외부에서 보이는 동작에 맞춰 코드를 고칠 수 있습니다.

가능한 한 실제 코드 경로를 통과시킨다

테스트 더블 (Test Double)이란 DB, 외부 API, 내부 협력 객체 등을 대신하는 가짜 객체의 총칭입니다.

mock (모의 객체), stub (스텁), fake (페이크) 등이 포함됩니다.

테스트 더블을 사용하면 테스트를 빠르고 독립적으로 실행할 수 있습니다.

반면, 의존 대상의 구현을 우회하기 때문에 컴포넌트 간의 결합부에서 발생하는 버그를 놓칠 수 있습니다.

/tdd는 가능한 한 실제 코드 경로를 통과하는 검증을 우선합니다.

에이전트가 작성한 코드는 단체로는 올바르게 보여도, 실제 호출 경로에서는 깨질 수 있습니다.

실제 코드 경로를 통과시키면 그 차이를 발견하기 쉬워집니다.

/diagnose가 삽입되는 것

/diagnose는 에이전트가 즉시 수정하게 만들지 않기 위한 절차입니다.

고장 난 코드를 보면 에이전트는 원인을 추측하여 변경하기 쉽습니다.

재현 조건도 판정 기준도 없는 상태에서 변경하면, "무엇을 고쳤는지"도 "고쳐졌는지"도 모호해집니다.

Diagnose (진단) 스킬의 흐름은 대략 다음과 같습니다.

Feedback loop → Reproduce → Minimise → Hypothesize → Instrument → Fix + regression test → Cleanup + Postmortem

여기서 첫 번째 feedback loop (피드백 루프)를 **Signal (시그널)**이라고 부릅니다.

Signal은 성패를 구분하기 위한 판정 기준입니다.

먼저 판정 기준을 정하고, 그 다음에 재현하고, 재현 범위를 좁힌 뒤, 가설을 세우고, 측정하여 수정합니다.

적절한 접점이 있는 경우에는 수정 전에 회귀 테스트 (Regression Test)를 만들어 실패를 확인합니다. 없다면 그 이유를 기록합니다.

Signal을 먼저 만든다

먼저 "이 입력에 대해 이 출력이 나오면 정상, 나오지 않으면 이상"이라는 기준을 정합니다.

테스트, CLI 출력, 로그의 특정 행 등 에이전트가 성패를 기계적으로 판정할 수 있는 형태라면 사용할 수 있습니다.

확인 수단 없이 조사를 시작하면 코드를 읽고 추측합니다.

그대로 변경하고 "고쳤습니다"라고 말합니다.

Signal을 먼저 만들면 에이전트는 변경 후에 동일한 판정 기준을 확인할 수 있습니다.

재현한 뒤에 만진다

다음으로 버그를 재현합니다.

재현할 수 없는 버그를 고치려 하면 에이전트는 코드의 겉모습만 보고 원인을 찾습니다.

그 결과 관계없는 곳을 바꾸기도 합니다.

재현할 수 있다면 가능한 한 작은 형태로 좁힙니다.

입력, 절차, 관련된 코드를 줄인 뒤에 수정에 들어가면 변경 전과 변경 후를 비교하기 쉬워집니다.

  • 변경 전은 실패한다
  • 변경 후는 통과한다

이 차이점이 수정의 근거가 됩니다.

가설을 3~5개 세운다

/diagnose는 하나의 추측에 바로 뛰어들지 않습니다.

여러 후보를 나열한 뒤에 조사합니다.

예를 들면 다음과 같습니다.

  • 이 변수가 null일지도 모른다
  • 이 함수가 호출되지 않았을지도 모른다
  • 이 타입 변환이 실패했을지도 모른다
  • 이 분기(Branch)에 들어가지 않았을지도 모른다

가설을 나열한 뒤, 어떤 것이 옳은지를 로그나 assert (단언)로 확인합니다.

이를 통해 에이전트가 첫 번째 추측만으로 큰 변경을 가하는 리스크를 낮춥니다.

Instrument로 확인한다

Instrument (계측)는 확인을 위해 로그나 assert를 넣어 실제 상태를 관측하는 공정입니다.

에이전트에게 "원인을 생각해봐"라고 전달하면 코드를 읽고 추측합니다.

"이 가설을 확인해봐"라고 전달하면 관측하는 방향으로 나아갑니다.

디버깅에서는 그럴듯한 설명보다 실제로 일어나고 있는 사실이 더 유용합니다.

Instrument(계측)는 그 사실을 가져오기 위한 과정입니다.

회귀 테스트와 정리까지 진행하기

축소된 재현 과정을 회귀 테스트(Regression Test)로 만들 수 있는 접점이 있다면, 수정하기 전에 테스트로 남겨둡니다.

먼저 해당 테스트가 실패하는 것을 확인하고, 그다음 수정하며, 마지막으로 통과하는 것을 확인합니다.

적절한 접점이 없는 경우에는 억지로 테스트화하지 말고, 그 이유를 기록합니다.

임시로 넣은 로그, assert, 디버깅용 출력은 역할이 끝나면 정리합니다.

수정만 하고 멈추면, 다음에 똑같은 방식으로 고장이 났을 때 다시 인간이 알아차려야 합니다.

회귀 테스트가 있다면 에이전트와 인간 모두 동일한 확인 수단을 사용할 수 있습니다.

재발을 방지하는 설계 고민하기

사후 분석(Postmortem)에서는 "어떻게 고쳤는가"뿐만 아니라 "어떤 설계라면 방지할 수 있었는가"를 생각합니다.

예를 들어, 다음과 같은 관점입니다.

  • 타입(Type)으로 방지할 수 없었는가
  • 경계(Boundary)에서 유효성 검사(Validation)를 할 수 없었는가
  • 테스트로 검출할 수 없었는가
  • 로그가 부족했는가
  • 책임(Responsibility)이 섞여 있지 않았는가

단, 모든 버그에 대해 설계를 바꿀 필요는 없습니다.

작은 수정과 회귀 테스트만으로 충분한 경우도 있습니다.

같은 종류의 버그가 유입되기 쉬운 구조라면 설계를 재검토합니다.

시작하기

npx skills@latest add mattpocock/skills

설치 시 /setup-matt-pocock-skills를 선택하여 실행하면, 이슈 트래커(Issue tracker), 분류 레이블(Triage labels), CONTEXT.md 및 ADR을 두는 위치를 기록할 수 있습니다. 다른 스킬들은 해당 기록을 공통 어휘로 사용할 수 있습니다.

이 설정은 /tdd/diagnose에 필수적인 것은 아닙니다. 소프트 의존성(Soft dependency)으로 설계되었기 때문에 기록이 없어도 동작합니다.

다음에 작은 기능을 추가할 때는 /tdd부터 시작하세요.

이미 발생한 버그를 추적할 때는 /diagnose부터 시작하세요.

에이전트에게 "생각해서 고쳐줘"라고 넘기는 것이 아니라,

"이 판정 기준을 만족하도록 진행해줘"라고 넘기세요.

그것만으로도 추측과 변경의 루프에 확인 단계를 넣을 수 있습니다.

Discussion

AI 자동 생성 콘텐츠

본 콘텐츠는 Zenn AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0