tdd는 Test Driven Development를 위한 스킬로, 엄격한 red-green-refactor 흐름, 공개 인터페이스 중심의 행동 기반 테스트, 통합 테스트 성향의 접근, 그리고 시스템 경계에서만 mocking을 사용하는 원칙을 익히도록 돕습니다.
이 스킬은 78/100점으로, 디렉터리에 올리기 좋은 탄탄한 후보입니다. 에이전트가 언제 호출해야 하는지 비교적 잘 판단할 수 있고, 일반적인 프롬프트보다 TDD에 특화된 더 나은 가이드를 기대할 수 있습니다. 다만 처음부터 끝까지 완전히 짜인 자동화 워크플로를 기대하기에는 무리가 있습니다.
- frontmatter만 봐도 TDD, red-green-refactor, integration test, test-first 같은 사용 신호가 분명해 호출 타이밍을 판단하기 쉽습니다.
- 무엇을 테스트해야 하고 무엇을 피해야 하는지에 대한 실행 지침이 좋으며, `tests.md`와 `mocking.md`에 구체적인 예시도 담겨 있습니다.
- 인터페이스 설계, deep modules, mocking 경계 설정, 사이클 이후 리팩터링 신호 등 실제 적용 품질을 높여 주는 보조 개념이 잘 정리되어 있습니다.
- `SKILL.md`에 빠른 시작이나 설치/실행 방법이 없어, 에이전트가 세션 안에서 적용 방식을 스스로 추론해야 합니다.
- 내용이 전반적으로 원칙과 예시에 중심을 두고 있어, 실제 기능 개발이나 버그 수정에 대한 단계별 TDD 진행 예시는 부족합니다.
tdd skill 개요
tdd skill은 단순히 “테스트 좀 써줘”라고 지시하는 범용 프롬프트가 아니라, 엄격한 red-green-refactor 루프에 따라 테스트 우선 개발을 수행하도록 돕는 집중형 가이드입니다. 특히 AI의 도움을 받아 기능을 만들거나 버그를 수정하되, 테스트를 구현 세부사항이 아니라 공개 인터페이스를 통한 동작에 묶어 두고 싶은 개발자에게 잘 맞습니다.
tdd skill은 이런 용도에 적합합니다
모델이 다음과 같이 움직이길 원한다면 Test Driven Development용 tdd를 사용하는 것이 좋습니다.
- 기능을 작은 세로 단위(vertical slice)로 계획하기
- 한 번에 실패하는 테스트 하나만 작성하기
- 통과에 필요한 최소한의 코드만 구현하기
- green 이후에 안전하게 리팩터링하기
- 무해한 리팩터링에도 쉽게 깨지는 취약한 테스트 피하기
tdd skill에서 가장 큰 가치를 얻는 사람
다음 조건이 이미 갖춰져 있다면 tdd skill의 효과가 가장 큽니다.
- 실행 가능한 테스트가 있는 코드베이스
- 타깃으로 삼을 수 있는 명확한 public API, endpoint, command, 또는 사용자 흐름
- 테스트 코드와 프로덕션 코드 모두 수정할 수 있는 권한
- 과도한 mocking보다 integration 스타일 테스트를 선호하는 성향
특히 실제 인터페이스를 통해 동작을 검증할 수 있는 백엔드 서비스, 라이브러리, 도메인 로직, 애플리케이션 플로우에서 유용합니다.
이 tdd skill이 다른 점
이 skill의 핵심 차별점은 테스트 품질에 대해 분명한 입장을 갖고 있다는 점입니다.
- 내부 구현이 아니라 동작을 테스트한다
- integration 스타일 테스트를 우선한다
- mock은 시스템 경계에서만 사용한다
- 모든 테스트를 먼저 다 쓰고 나중에 코드를 한꺼번에 작성하는 “수평 분할(horizontal slicing)”을 피한다
- TDD를 단순 커버리지 추가가 아니라 더 나은 인터페이스를 만드는 도구로 사용한다
그래서 tdd usage는 AI에게 “테스트와 구현을 작성해줘”라고 요청하는 일반적인 프롬프트보다 훨씬 더 규율 있게 작동합니다.
tdd skill 도입을 가로막을 수 있는 요소
테스트를 실행할 수 없는 환경이거나, 코드베이스에 안정적인 public seam이 없거나, 팀이 snapshot 중심 또는 mock 중심의 단위 테스트를 주로 원한다면 이 skill과의 궁합은 떨어집니다. 또한 한 번에 기능 전체를 생성하는 방식이 아니라, 작은 단계로 반복해 나갈 의지가 있다는 전제를 둡니다.
tdd skill 사용 방법
skills 환경에 tdd 설치하기
리포지토리의 Skills 시스템을 사용 중이라면, 일반적인 설치 패턴은 다음과 같습니다.
npx skills add mattpocock/skills --skill tdd
설치 후에는 테스트 우선 워크플로로 동작을 구현하거나 수정하도록 모델에 요청할 때 tdd를 호출하면 됩니다.
tdd skill을 본격적으로 쓰기 전에 먼저 읽을 파일
이 skill을 가장 빠르게 이해하는 순서는 다음과 같습니다.
SKILL.mdtests.mdmocking.mdinterface-design.mdrefactoring.mddeep-modules.md
이 순서에는 의미가 있습니다. SKILL.md가 전체 운영 철학을 설명하고, 나머지 파일들은 실제로 “좋은 테스트”와 “좋은 설계”가 무엇인지 구체적으로 풀어 줍니다.
tdd skill이 기대하는 핵심 워크플로 이해하기
이 skill은 촘촘한 반복 루프를 전제로 설계되어 있습니다.
- 작은 동작 하나를 고른다
- 공개 인터페이스를 통해 실패하는 테스트 하나를 작성한다
- 통과에 필요한 최소 코드만 구현한다
- 테스트를 green으로 유지한 채 리팩터링한다
- 그다음 가장 작은 slice로 반복한다
처음부터 기능 전체를 한 번에 요청하면 tdd usage의 핵심 가치 대부분을 놓치게 됩니다.
구현 아이디어가 아니라 동작부터 시작하세요
좋은 입력:
- “만료된 카드에 대한 checkout 지원을 추가해줘. Public entrypoint는
checkout(cart, paymentMethod)이고, 기존 테스트 파일은checkout.test.ts야. integration-style 테스트를 계속 써줘.”
아쉬운 입력:
- “결제 orchestration용 클래스를 만들고 각 메서드에 대한 unit test를 추가해줘.”
첫 번째 프롬프트는 skill에 동작 기준의 목표를 줍니다. 반면 두 번째는 내부 설계를 추측하게 만들고, 깨지기 쉬운 테스트로 흐르기 쉽습니다.
공개 인터페이스와 테스트 명령을 함께 제공하세요
좋은 tdd install 및 실행 결과를 얻으려면 다음 정보를 포함하는 것이 좋습니다.
- 테스트 대상 함수, route, CLI command, 또는 UI action
- 테스트 파일 위치
- test runner와 실행 command
- DB, HTTP, 외부 서비스 같은 관련 제약
- mock 가능 범위와 불가능 범위
실전용 프롬프트 템플릿은 다음과 같습니다.
Use the tdd skill.
Goal: Add [behavior].
Public interface: [function/route/command].
Test location: [path].
Run tests with: [command].
Boundaries to mock: [external API, clock, filesystem].
Do not mock: [internal modules/classes].
Work in red-green-refactor steps and explain each step briefly.
수평 분할이 아니라 세로 분할로 진행하세요
이 리포지토리에서 얻을 수 있는 가장 실용적인 교훈 중 하나는, 처음부터 테스트를 한꺼번에 몰아서 작성하지 말라는 점입니다. 여기서 좋은 tdd usage란 다음을 뜻합니다.
- 실제 시나리오 하나를 고른다
- 그것을 통과시킨다
- 그 결과를 바탕으로 다음 시나리오를 정한다
이 방식은 상상 속 추상화를 줄여 주고, 대체로 더 나은 API 형태로 이어집니다.
tdd에서는 integration 스타일 테스트를 우선하세요
이 리포지토리는 public API를 통해 실제 코드 경로를 실행하는 테스트를 강하게 선호합니다. 실제로는 다음을 의미합니다.
- private helper 대신 export된 함수를 호출한다
- route handler를 지원되는 인터페이스로 검증한다
- 내부 호출 순서가 아니라 관찰 가능한 결과를 검증한다
- 테스트 이름을 “user can checkout with valid cart”처럼 기능 중심으로 짓는다
리팩터링으로 내부 구현이 바뀌어도 동작이 같다면, 좋은 테스트는 대체로 계속 green이어야 합니다.
mock은 시스템 경계에서만 사용하세요
tdd skill은 mock 자체를 반대하지 않습니다. 대신 자기 구현을 mock하는 방식을 경계합니다. 다음은 mock해도 됩니다.
- payment gateway
- email provider
- 시간/난수
- 테스트 환경에 따라 database 또는 filesystem
다음은 mock하지 않는 편이 좋습니다.
- 자신의 모듈
- 내부 collaborator
- private method
- 직접 제어 가능한 얇은 wrapper
이 원칙 하나만 지켜도, 대부분의 프롬프트 미세 조정보다 결과 품질이 크게 좋아집니다.
코드를 많이 쓰기 전에 테스트 가능한 구조부터 만드세요
보조 문서들이 강조하는 중요한 포인트는, 더 좋은 인터페이스가 TDD를 더 쉽게 만든다는 점입니다. 모델에게 다음과 같은 코드를 선호하도록 요청하세요.
- 의존성을 내부에서 생성하지 않고 주입받는다
- 숨은 상태를 변경하기보다 결과를 반환한다
- public surface area를 작게 유지한다
현재 설계가 테스트를 지나치게 어렵게 만든다면, 먼저 더 작고 테스트하기 쉬운 public interface를 제안하도록 요청하는 것이 좋습니다.
강한 tdd 프롬프트 예시
Use the tdd skill to add password reset token expiry.
Context:
- Node + TypeScript
- Public API: `requestPasswordReset(email)` and `resetPassword(token, newPassword)`
- Tests: `src/auth/password-reset.test.ts`
- Run with: `pnpm test password-reset`
- Mock only email sending and time
- Do not mock repository code or internal services
Please:
1. choose the smallest failing behavior first
2. write integration-style tests through public APIs
3. implement minimum code to pass
4. refactor after green
5. avoid asserting internal call counts unless at an external boundary
이 예시가 잘 작동하는 이유는, skill에 목표와 경계 정책, 그리고 실제 실행 경로를 함께 제공하기 때문입니다.
tdd skill 결과물의 품질 신호를 확인하세요
이 skill로부터 좋은 tdd guide 결과가 나오면 보통 다음 특징이 보입니다.
- 테스트 이름이 사용자에게 보이는 동작 중심이다
- 한 번에 작은 시나리오 하나만 다룬다
- 각 단계 구현이 최소한이다
- green 이후 리팩터링 메모가 있다
- private structure와의 결합이 거의 없다
반대로 좋지 않은 결과에는 대개 다음이 보입니다.
- 내부 코드에 대한 mock이 많다
- 호출 순서를 검증한다
- 첫 단계부터 거대한 테스트 묶음을 만든다
- 어떤 동작도 통과하기 전에 추상화를 앞세운다
tdd skill FAQ
tdd는 완전히 새로운 기능에만 적합한가요?
아닙니다. tdd skill은 버그 수정에도 잘 맞습니다. 성숙한 코드베이스에서는 public interface를 통해 버그를 재현하는 실패하는 회귀 테스트를 먼저 만들고, 그다음 최소 수정, 마지막으로 정리하는 흐름이 가장 좋은 출발점인 경우가 많습니다.
이 tdd skill은 초보자도 쓰기 쉬운가요?
네, 프로젝트의 테스트를 어떻게 실행하는지만 이미 알고 있다면 충분히 접근 가능합니다. 가이드는 분명한 취향을 갖고 있지만 단순합니다. 동작을 테스트하고, slice를 작게 유지하고, 구현 세부사항에 대한 assertion을 피하라는 것입니다. 다만 완전 초보자라면 프로젝트 아키텍처와 테스트 도구를 이해하는 데 추가 도움이 필요할 수 있습니다.
AI에게 그냥 테스트를 작성해 달라고 하는 것과 tdd는 무엇이 다른가요?
일반 프롬프트는 커버리지 위주이거나 mock이 많은 테스트를 만들기 쉽습니다. tdd skill은 모델을 다음 방향으로 밀어 줍니다.
- 동작 중심 명세
- 더 안전한 리팩터링
- 더 깔끔한 인터페이스
- 더 작은 반복 단계
이 차이는 테스트뿐 아니라 프로덕션 설계 자체도 바꿉니다.
어떤 경우에는 tdd를 쓰지 않는 편이 좋나요?
다음 상황에서는 Test Driven Development용 tdd를 건너뛰거나 제한적으로 쓰는 편이 좋습니다.
- 아직 동작을 의미 있게 검증할 수 없는 경우
- 반복 과정에서 환경 실행 비용이 너무 큰 경우
- 버리고 실험해 보는 exploratory spike를 하는 경우
- 이름 변경이나 dependency bump처럼 작업이 대부분 기계적인 경우
다만 public seam이 더 명확해진 뒤에는 다시 TDD로 돌아올 수 있습니다.
tdd는 integration 테스트만 요구하나요?
엄격하게 그렇지는 않지만, 실제 인터페이스를 통한 integration 스타일 테스트 쪽으로 무게가 실려 있습니다. 목표는 테스트를 무조건 크게 만드는 것이 아니라, 안정적인 seam에서 동작을 검증하는 것입니다. public interface를 유지하고 내부 결합만 피할 수 있다면, 작고 집중된 테스트도 충분히 괜찮습니다.
어떤 언어와 프레임워크가 이 skill에 잘 맞나요?
핵심 아이디어는 대체로 언어에 구애받지 않습니다. 예시는 TypeScript와 JavaScript 쪽에 치우쳐 있지만, 명확한 public interface와 테스트 경계를 정의할 수 있는 환경이라면 Python, Java, Go, Ruby 등 비슷한 생태계에도 동일한 설계 원칙을 적용할 수 있습니다.
tdd skill 개선 방법
tdd의 첫 slice를 더 작게 잡으세요
tdd 결과를 가장 쉽게 개선하는 방법은 첫 단계를 줄이는 것입니다. “사용자 초대 기능을 만들어줘” 대신 “유효한 이메일을 가진 사용자가 초대를 요청할 수 있게 해줘”처럼 시작하세요. slice가 작을수록 AI가 상상으로 아키텍처를 부풀릴 가능성이 줄고, 테스트도 더 깔끔해집니다.
경계 규칙을 명시적으로 주세요
좋지 않은 출력은 mocking 정책이 모호할 때 많이 발생합니다. 모델에게 다음을 정확히 알려 주세요.
- 어떤 외부 시스템은 mock 가능한지
- 어떤 내부 모듈은 실제로 유지해야 하는지
- 테스트 DB를 사용할 수 있는지
- 시간을 주입해야 하는지, 아니면 고정해야 하는지
이렇게 해야 skill이 리포지토리의 철학과 일관되게 작동합니다.
공개 인터페이스 기준의 테스트 이름을 요구하세요
더 좋은 테스트를 원한다면, 결과를 설명하는 이름을 요청하세요.
- 좋음:
user can checkout with valid cart - 약함:
checkout calls payment service
이 한 줄 지시만으로도 구현 세부사항 쪽으로 미끄러지는 문제를 자주 막을 수 있습니다.
red-green-refactor가 눈에 보이게 강제하세요
첫 응답이 구현 전체를 한 번에 쏟아내는 식이라면, 모델에게 다음처럼 다시 구조화하라고 요청하세요.
- 첫 번째 실패 테스트를 보여줄 것
- 통과에 필요한 최소 코드만 보여줄 것
- 리팩터링은 별도로 설명할 것
- 필요하면 한 slice에서 멈출 것
tdd skill은 루프가 암묵적인 상태보다, 눈에 보이게 드러날 때 가장 잘 작동합니다.
테스트가 어색하면 설계부터 개선하세요
모델이 깔끔한 테스트를 잘 쓰지 못한다면, 문제는 테스트 문법이 아니라 인터페이스 설계인 경우가 많습니다. 다음 방향으로 수정하도록 요청하세요.
- dependency injection
- 명시적인 입력과 출력
- 더 작은 public surface
- 더 적은 side effect
이 지점에서 interface-design.md와 deep-modules.md가 특히 큰 도움이 됩니다.
리팩터링을 별도의 품질 점검 단계로 쓰세요
몇 개의 slice가 green이 된 뒤에는, 리포지토리의 기준을 활용해 별도의 리팩터링 리뷰를 명시적으로 요청하세요.
- duplication
- long methods
- shallow modules
- feature envy
- primitive obsession
이렇게 하면 tdd usage가 “테스트 통과”에서 멈추지 않고, 동작을 바꾸지 않으면서 유지보수성까지 끌어올릴 수 있습니다.
흔한 실패 패턴은 초기에 바로잡으세요
출력 품질이 떨어진다면 보통 원인은 다음 중 하나입니다.
- 첫 실패 테스트 전에 코드가 너무 많이 생성됨
- 내부 collaborator를 과도하게 mock함
- 테스트가 구현 세부사항을 검증함
- 기능 요청이 한 사이클에 비해 너무 큼
- public interface가 불분명하거나 단계마다 계속 바뀜
이럴 때는 동작 하나, seam 하나, 실패 테스트 하나로 다시 리셋하세요.
리포지토리 파일을 의사결정 도구로 활용하세요
더 나은 결과를 위해, 문제 유형을 보조 문서에 연결해 보세요.
- 테스트 스타일이 약할 때는
tests.md - 경계 판단이 모호할 때는
mocking.md - seam이 어색할 때는
interface-design.md - green 이후에는
refactoring.md - API shape가 너무 넓어질 때는
deep-modules.md
이 읽기 경로는 SKILL.md만 훑는 것보다 훨씬 실질적인 도움을 줍니다.
같은 프롬프트 반복보다 제약을 더 촘촘히 하세요
첫 출력이 평범했다면, 그냥 “다시 해봐”라고 하지 마세요. 다음 라운드에서는 구체적인 제약을 추가해 개선하는 편이 낫습니다.
- 동작 하나만 대상으로 할 것
- 현재 public API를 유지할 것
- 내부 모듈은 mock하지 말 것
- repository mock보다 테스트 DB를 우선할 것
- 첫 red-green-refactor cycle 뒤에는 멈출 것
이런 식의 반복은 더 많은 설명을 요구하는 것보다 tdd guide 품질을 훨씬 안정적으로 끌어올립니다.
