AI 코딩 에이전트를 위한 나만의 TDD 스킬
현재 AI 에이전트는 학습 데이터의 한계로 인해 테스트 코드 작성에 매우 서툽니다. 하지만 켄트 벡(Kent Beck)의 정석적인 TDD 원칙과 '명세-인코딩-이행(Specify-Encode-Fulfill)' 루프 같은 명확한 가이드라인을 제공하면, AI도 논리적이고 의미 있는 테스트를 작성할 수 있습니다. 이 글은 AI가 스스로 테스트 설계 오류를 점검하게 하고 불필요한 코드 작성을 방지하는 실용적인 에이전트 활용법을 소시합니다.
Jason Swett의 '테스트 주도 개발(TDD)을 위한 나만의 에이전트 스킬'
AI 에이전트는 적어도 이 글을 작성하는 현재까지도 테스트를 작성하는 데 서툽니다. 에이전트가 작성한 테스트는 종종 모호하고, 알아보기 어렵고, 지나치게 복잡하며, 임시방편적이고, 체계가 없으며, 동어반복적이고, 보여주기식이고, 대충 때우는 느낌이며, 완전히 무의미할 때가 많습니다.
안타깝게도 저는 별다른 지도 없이는 에이전트들이 당장 테스트 작성 실력을 크게 향상시킬 것이라고 기대하지 않습니다. 왜냐하면 에이전트는 인간이 작성한 사례를 통해 학습하는데, 솔직히 말해 인간이 작성한 예시들 역시 대체로 좋지 않기 때문입니다. '초보자'들이 작성한 테스트의 품질이 낮을 뿐만 아니라, 안타깝게도 강사들이 가르치는 테스트 방식도 종종 꽤 형편없습니다. 현재 상황은 정말 처참합니다.
다행히 좋은 소식은, 약간의 가이드만 제공해도 에이전트가 합리적인 TDD 프로세스를 따르고 명확하고 의미 있는 테스트를 작성할 수 있다는 것입니다. 그 가이드는 정확히 무엇일까요? 진실에 아주 가까운 짧은 대답은 켄트 벡(Kent Beck)의 정석적인 TDD(Canon TDD)입니다. 에이전트의 스킬에 "켄트 벡의 정석 TDD를 따르라"는 지시 하나만 추가해도 원하는 결과의 약 60%는 달성할 수 있을 것입니다.
조금 더 긴 대답은 제가 직접 나만의 TDD 스킬에 녹여낸 내용과 같습니다.
나만의 TDD 스킬
이 가이드는 계속 업데이트되는 살아있는 문서이기 때문에, 블로그 포스트에 작성하여 영원히 멈춰버리게 두고 싶지 않았습니다. 대신 GitHub에서 저의 TDD 스킬을 확인할 수 있습니다. 그렇지만 그 핵심은 변하지 않을 것이 확실하므로 여기에 그 본질을 공유하겠습니다.
먼저 저는 에이전트에게 제가 '명세-인코딩-이행(specify-encode-fulfill)' 루프라고 부르는 개념을 알려줍니다. 이는 기존의 '레드-그린-리팩토링(red-green-refactor)'을 대체하는 저만의 방식입니다.
명세-인코딩-이행(SEF)은 다음과 같이 진행됩니다:
명세(Specify): 구축하고자 하는 것의 명세를 작성합니다. 인코딩(Encode): 그 명세를 자동화된 테스트(실행 가능한 명세)로 인코딩합니다. 이행(Fulfill): 명세를 충족시키는 코드를 작성합니다.
SEF는 저에게 TDD가 무엇인지 보여주는 높은 수준의 관점입니다. 조금 더 구체적인 수준에서는 켄트 벡의 정석 TDD가 있으며, 이를 제 나름의 말로 아래와 같이 설명할 수 있습니다.
- 현재 TDD 세션의 범위 내에 있는 명세 목록을 작성합니다.
- 목록의 각 항목을 자동화된 테스트로 인코딩합니다.
- 현재 테스트 실패를 해결하기 위해 딱 맞는 최소한의 코드만 수정합니다. '투기적 코딩(Speculative coding)'을 피하세요. 현재 테스트 실패를 해결하는 데 필요한 것보다 더 많은 코드를 작성하면, 어떤 테스트도 실행되지 않는 코드를 만들 위험이 있습니다.
- 선택적으로 리팩토링을 수행하되, 동작 변경을 커밋하기 전에는 리팩토링을 하지 마세요. 동작 변경과 리팩토링을 절대 섞지 마세요.
- 목록이 빌 때까지 2번 항목으로 돌아갑니다.
나의 TDD 스킬에는 조금 더 많은 세부 사항이 포함되어 있지만, 이것이 프로세스의 핵심입니다. 하지만 이 프로세스는 테스트 자체의 설계에는 큰 영향을 미치지 않으므로, 이를 위해 '테스트 설계 검토(Test Design Review)'라는 별도의 스킬을 사용합니다.
테스트 설계 검토 스킬은 편향을 피하기 위해 별도의 에이전트를 생성하여, (예를 들어 테스트가 목적이 아닌 수단에 초점을 맞추는 경우와 같은) 설계 원칙 위반을 찾아내고 수정 제안을 합니다. 때로는 이 '수정'이 모호할 때도 있지만 대체로 정확합니다. 에이전트가 특정 테스트를 작성한 방식에 만족하지 못할 때, 저는 에이전트가 스스로 실수를 찾아낼 수 있도록 이 테스트 설계 검토를 실행합니다.
일반적인 설계 검토
많은 테스트 설계 위반은 "사물을 있는 그대로 호출하라"와 같은 일반적인 소프트웨어 설계 원칙을 위반한 것일 뿐입니다. 테스트 설계 검토 스킬을 통해 테스트를 검토하는 것 외에도, '소프트웨어 설계 검토(Software Design Review)' 스킬을 통해 테스트를 한 번 더 검토하는 것을 선호합니다.
에이전트는 저를 놀라게 할 때가 있습니다. 제 TDD 스킬에 "작성하려는 테스트를 작성하기 어렵다면, 그것은 식사를 하기 전에 먼저 주방을 청소해야 한다는 신호일 수 있다"는 지시를 별다른 기대 없이 포함시켰습니다. 그런데 어떤 이유에서인지 Claude가 이 지시를 아주 진지하게 받아들여서, 심심하면 잠시 멈추고 혹시 주방을 청소해야 하는지 묻곤 합니다. 그리고 실제로 대부분의 경우 청소를 해야 하는 상황이 맞았습니다.
아직 저는 제 에이전트가 글을 완벽하게 작성하게 하지는 못했습니다.