1
0
Fork 0
Everything2Everything/docs/tdd/02_AGENTIC_TDD.md
Yun Chan 4cd9c678c0
Some checks are pending
Forgejo Release / build-and-release (push) Waiting to run
feat(tdd): implement SSOT canon, AGENTS.md, ultra-strict design audit, E2E scenarios, and Forgejo release pipeline
2026-09-03 12:21:40 +09:00

7.2 KiB
Raw Permalink Blame History

02. 20252026 AI Agentic TDD 최신 동향 & 실전 프랙티스

"Without rigorous, automated verification hooks, autonomous coding agents do not converge on correct solutions; they diverge into unmaintainable 'vibe code'." — Agentic Software Engineering Patterns (arXiv, 2026)

이 문서는 20252026년 AI 에이전트(Autonomous AI Agents)와 대규모 언어 모델(LLM) 환경에서 TDD가 왜 필수불가결한 핵심 생명선인지, 그리고 이를 운영하기 위한 최신 아키텍처 패턴을 정의한다.


1. 바이브 코딩(Vibe Coding)의 파멸과 Agentic TDD의 필연성

1.1 자율 코딩 에이전트의 3대 퇴행 현상

LLM 에이전트에게 단순 자연어로 "이 기능을 추가해줘"라고 요청할 때 발생하는 전형적인 장애:

  1. 사일런트 리그레션 (Silent Regression): 한 부분을 고치면서 기존에 작동하던 다른 서브시스템의 동작을 소리 없이 파괴함.
  2. 환각 인터페이스 (Hallucinated Contracts): 존재하지 않는 메서드, 잘못된 열거형 값, 비표준 XAML 속성을 자연스럽게 지어내어 런타임에 크래시 발생.
  3. 토큰 소모 루프 (Token Burn Loop): 코드를 마구잡이로 고치고 실행해본 뒤 에러가 나면 또 다른 추측성 코드를 덧붙여 컨텍스트 윈도우를 오염시키고 수백만 토큰을 낭비함.

1.2 TDD: 에이전트의 불변 안전망 (The Agent Invariant Guardrail)

  • 에이전트에게 테스트란?: 단순한 검증 도구가 아니라, **완벽하고 모호함이 없는 실행 가능한 명세서(Executable Specification)**이다.
  • 자연어 지침은 모델에 따라 다의적으로 해석될 수 있으나, C# xUnit의 Assert.Equal(expected, actual)은 1비트의 모호함도 허용하지 않는다.
  • 테스트가 통과(GREEN)했다는 객관적 사실만이 에이전트의 작업 완료를 입증할 수 있는 유일한 기준이다.

2. Agentic TDD 핵심 아키텍처 패턴 (2026 Best Practices)

2.1 적대적 명세-검증 루프 (Adversarial Specification & Verification)

최신 에이전트 아키텍처에서는 기능 구현자와 검증자를 분리하거나, 인지 모드를 전환하여 검증을 수행한다:

┌────────────────────────────────────────────────────────┐
│ 1. Specifier / Tester Mode                             │
│    - 요구사항을 분석하여 엣지 케이스를 포함한 RED 테스트 작성 │
│    - 의도된 실패(RED)를 터미널에서 확인                       │
└─────────────────────────┬──────────────────────────────┘
                          ▼
┌────────────────────────────────────────────────────────┐
│ 2. Implementer Mode                                    │
│    - 테스트를 만족시키는 가장 정갈하고 최소한의 코드 작성   │
│    - GREEN 전환 확인                                    │
└─────────────────────────┬──────────────────────────────┘
                          ▼
┌────────────────────────────────────────────────────────┐
│ 3. Adversary / Mutation Mode                           │
│    - 테스트가 엉터리로 통과한 것은 아닌지 의심              │
│    - 코드를 변소(Mutate)시켜 테스트가 즉시 깨지는지 검증      │
└────────────────────────────────────────────────────────┘

2.2 실패 유도 자가 치유 (Fail-Guided Self-Repair)

  • 에이전트가 실패 메시지를 마주했을 때 직관이나 추측으로 코드를 바꾸지 않는다.
  • 오류 분석 프로토콜:
    1. Expected: <기대값> vs Actual: <실제값>의 구체적 차이를 문자 단위로 분석.
    2. 스택 트레이스의 정확한 파일명과 라인 번호(file.cs:L42)로 즉시 점프.
    3. 해당 지점의 로직 분기 또는 상태 전이 불일치를 확인하고 정밀 타격 수정.

2.3 Pre-Write & Pre-Test Invariant Hooks

  • 에이전트 도구 호출 체계에서 소스 코드를 수정(replace_file_content 또는 write_to_file)하기 전, 해당 기능에 대응하는 테스트 파일이 변경되었거나 존재하는지 감시한다.
  • 테스트 코드의 보강 없이 프로덕션 코드만 광범위하게 수정하는 행위는 TDD 규약 위반으로 간주하여 차단한다.

3. 뮤테이션 테스팅 (Mutation Testing as Test Quality Gate)

3.1 100% 코드 커버리지의 함정

  • 코드 라인이 실행되었다고 해서 그 코드가 올바르게 검증된 것은 아니다. (예: Assert가 없거나, Assert.True(true)처럼 무의미한 단언).
  • 특히 AI 에이전트가 생성한 테스트는 형식적으로는 통과하지만 실제 버그를 잡지 못하는 "껍데기 테스트"가 될 위험이 있다.

3.2 뮤테이션 점수 (Mutation Score)

  • 프로덕션 코드에 고의로 인위적인 결함(Mutants)을 주입한다:
    • 조건문 반전: if (a > b)if (a <= b)
    • 산술 연산자 교체: count + 1count - 1
    • 반환값 변경: return truereturn false
    • 문장 제거: 메서드 호출 주석 처리
  • 살아남은 돌연변이 (Survived Mutant): 코드가 망가졌는데도 테스트가 통과했다면, 그 테스트는 무가치한 쓰레기다.
  • 사살된 돌연변이 (Killed Mutant): 코드가 망가지자마자 테스트가 즉시 RED로 터지면, 그 테스트는 진정한 가치를 지닌 방어선이다.
  • Everything2Everything은 핵심 변환 라우팅(ConversionGraph), 손실 등급 분류(LossClass), 인코더 옵션 빌더에 대해 높은 뮤테이션 사살율(>85%)을 목표로 삼는다.

4. 토큰 경제학과 피드백 루프 속도 (Token Economics & Velocity)

테스트 유형 피드백 주기 토큰 소모량 디버깅 복잡도 권장 비율
순수 C# 단위 테스트 0.05초 ~ 0.5초 0 (로컬 실행) 매우 낮음 (원인 즉시 식별) 최우선 (70%)
XAML 정적 AST 감사 0.1초 ~ 0.3초 0 (로컬 파싱) 낮음 (정확한 XAML 라인 지목) 디자인 필수 (20%)
STA Visual Tree 측정 0.5초 ~ 1.5초 0 (In-Memory) 보통 (레이아웃 트리 추적) UI 통합 (10%)
GUI 수동 실행 / 프로세스 폴링 10초 ~ 120초 극대 (스크린샷/로그 반복) 극도로 높음 최소화 (스모크 전용)

빠른 로컬 단위/AST 테스트가 1초 내에 성공/실패 결과를 반환할 때, 에이전트의 인지 부하는 최소화되고 성공 확률은 기하급수적으로 증가한다.