AI 코딩 도구

AI로 TDD: Claude Code로 레드-그린-리팩터 테스트 작성하기 (2026)

2026년 8월 21일10분 읽기

AI로 하는 TDD는 먼저 실패하는 테스트를 작성하고, Claude Code가 그것을 그린으로 만드는 최소한의 코드를 작성하게 한 뒤, 그린을 유지하면서 리팩터링하는 것을 뜻해요 — 바로 레드 -> 그린 -> 리팩터 루프예요. 테스트는 AI가 스스로에게 부여할 수 없는 "완료의 정의" 역할을 해요. 가장 중요한 함정 하나: Claude는 기본적으로 코드를 먼저 작성하려 하기 때문에, 단계를 분리한 프롬프트와 CLAUDE.md의 규칙을 이용해 테스트를 먼저 작성하도록 적극적으로 강제해야 해요.

AI로 하는 TDD란 무엇인가요?

TDD(테스트 주도 개발)는 테스트를 먼저 작성하고 — 실패하게 두고 — 그다음 그것을 통과시킬 만큼만 코드를 작성한 뒤, 마지막으로 테스트를 다시 레드로 만들지 않으면서 코드를 정리(리팩터)하는 코드 작성 방식이에요. 이것이 "클래식" TDD이고, 수년 전부터 있어 왔어요. "AI로 하는 TDD"는 단지 요건 정의와 결과 검증은 여러분이 맡고, 테스트를 작성하는 일과 그것을 만족시키는 구현을 작성하는 일 둘 다를 Claude Code(또는 비슷한 AI 어시스턴트)에게 맡긴다는 뜻이에요.

"AI에게 코드를 짜게 한 다음 나중에 테스트를 붙이게 하는" 방식과의 핵심 차이는 순서예요. TDD에서 먼저 작성하는 테스트는 실행 가능한 명세예요. 실제 코드가 한 줄도 존재하기 전에 정확한 입력, 출력, 엣지 케이스를 기술하죠. 그러면 Claude Code는 제멋대로 코드를 짜고 자기 숙제를 스스로 채점하는 대신, 그 테스트를 그린으로 만드는 코드를 작성하게 돼요.

AI와 함께 프로세스를 진행하는 게 아직 익숙하지 않다면, 먼저 바이브 코딩이 무엇이고 규율 있는 워크플로와 어떻게 다른지를 읽고 TDD가 큰 그림에서 어디에 들어맞는지 살펴보세요. TDD는 바이브 코딩이 아무도 통제할 수 없는 코드 더미로 변하지 않게 지켜 주는 규율 중 하나예요.

왜 TDD는 Claude Code와 그토록 잘 맞을까요?

Claude Code는 "완료의 정의"가 실행 가능하고 스스로 검증되는 무언가일 때 최고의 성능을 내요 — 그리고 테스트가 바로 그것이에요. "이 함수가 제대로 동작하게 해줘"라고 말하면 AI는 여러분의 의도를 추측해야 해요. "이 8개의 테스트를 통과시켜줘"라고 말하면, 레드냐 그린이냐라는 명확한 이진 목표가 생기고, AI가 "이제 됐겠지"라고 넘겨짚을 수 있는 회색 지대가 없어요.

이 조합이 딱 맞아떨어지는 이유는 세 가지예요:

  • 테스트는 명세이자 동시에 안전망이에요. 요건을 기술하는 동시에, AI가 실수로 다른 무언가를 바꾼 순간 그 고장을 잡아내요. AI가 끊임없이 편집하는 코드베이스에서, 그 안전망이 "하나 고치고 셋 망가뜨리는" 사태를 막아 줘요.
  • 촘촘한 피드백 루프. 테스트 작성 -> 실행 -> 오류 읽기 -> 그린이 될 때까지 수정. Claude Code는 터미널에서 테스트를 실행하고 실제 출력을 읽을 수 있어서, 여러분이 손으로 오류를 복사해 붙여넣지 않아도 여러 라운드에 걸쳐 스스로 반복해요.
  • AI가 요건을 놓치는 것을 막는 방어막. 이건 사람들이 잘 입 밖에 내지 않는 지점이에요. 테스트를 먼저 작성하면 여러분(과 AI)은 코딩하기 전에 요건을 확정할 수밖에 없어요. 요건이 테스트로 굳어지고 나면 "기술적으로는 맞지만 의도가 틀린" 버그가 상당수 사라져요.

Anthropic도 Claude Code 모범 사례(Anthropic, 2025)에서 Claude Code로 작업할 때 권장하는 워크플로로 TDD를 꼽고 있어요. 테스트를 작성하고, 그것이 실패하는지 확인한 다음, 통과할 때까지 코드를 작성하는 방식이죠. 이건 누군가가 지어낸 요령이 아니라, 도구를 만든 당사자가 제안하는 사용법이에요.

Claude Code로 하는 레드-그린-리팩터 사이클

TDD 전체는 세 단계에 담기고, 기능의 작은 조각마다 반복해요. Claude Code에서는 각 단계가 하나의 프롬프트와 하나의 명확한 출력 기대치에 대응해요.

1단계 - 레드: 실패하는 테스트 작성하기 (아직 코드 없음)

원하는 동작에 대한 테스트, 그리고 테스트만 Claude에게 작성해 달라고 해요. 구현이 아직 존재하지 않으니 실행하면 반드시 레드여야 해요.

Write a unit test for validate_email(email) in src/validators.py using pytest.
Cover these cases: valid email, missing @, missing domain, empty string, None.
The test MUST fail because the function does not exist yet. Do NOT write any code for validate_email.

예상 결과: 몇 가지 케이스가 담긴 test_validators.py 파일이 생기고, pytest를 실행하면 ImportError나 레드 테스트가 보고돼요. 여기서 레드는 올바른 상태예요 — 테스트가 아직 존재하지 않는 무언가를 실제로 검사하고 있다는 증거니까요.

2단계 - 그린: 통과시킬 최소한의 코드 작성하기

이제서야 AI에게 구현을 작성하게 하고, 여분의 기능을 덧붙이지 않도록 "최소한"을 강조해요.

Write the MINIMAL implementation of validate_email so every test in
test_validators.py passes. Run `pytest -q` and paste the real results back to me.
Do not add features beyond what the tests cover.

예상 결과: 딱 필요한 만큼의 코드가 생기고 pytest 출력이 그린으로 바뀌어요. AI가 실제 실행 출력을 붙여넣게 하세요. 그냥 "통과합니다"라는 말만 믿지 마세요.

3단계 - 리팩터: 코드를 정리하고 그린을 유지하기

일단 그린이 되면, 자유롭게 정리할 수 있는 안전망이 생긴 거예요.

Refactor validate_email for readability (extract the regex into a constant, use clear names).
Do NOT change behavior. Re-run `pytest -q` after editing to prove it is still green.

예상 결과: 더 깔끔한 코드가 되고, 테스트는 여전히 완전히 그린이에요. 리팩터 도중에 테스트가 레드가 되면, 그건 방금 실수로 동작을 바꿨다는 신호예요 — 즉시 고치세요.

Claude Code로 하는 실제 테스트 우선 세션 (단계별로)

여기까지가 이론이고, 이제 작은 기능에 대한 실제 세션을 볼게요. 정수 1299000을 반환하는 함수 parse_price("1.299.000d")예요. 입력/출력이 명확한 순수 로직이라 — TDD에 이상적인 소재예요.

1단계 - 레드 테스트 요청하기. 프로젝트 폴더에서 Claude Code를 열고 이렇게 입력해요:

Write pytest for parse_price(s) in src/pricing.py:
- "1.299.000d" -> 1299000
- "50.000 d" -> 50000
- "0d" -> 0
- a string with no digits -> raise ValueError
Write only the test. The function does not exist yet, so the test must fail.

2단계 - 그린으로 만들 최소한의 코드 요청하기. 테스트가 예상대로 레드인지 확인한 뒤에:

Write the minimal implementation of parse_price so all 4 tests pass.
Run `pytest -q` and paste the output. Do not handle cases outside the tests.

Claude는 숫자가 아닌 문자를 제거하고 int로 캐스팅하며, 비어 있으면 ValueError를 던지는 함수를 작성해요. 스스로 테스트를 실행하고 그린 결과를 돌려줘요.

3단계 - 리팩터. 저는 Claude에게 숫자 추출 로직을 헬퍼로 빼내고 docstring을 추가하며, 동작이 바뀌지 않았음을 증명하기 위해 테스트를 다시 실행하라고 지시해요. 여전히 4개 모두 그린이에요. 세션 전체가 몇 분밖에 걸리지 않고, 핵심은 "됐다"를 그냥 믿을 필요가 한 번도 없었다는 거예요 — 모든 주장에 실제 pytest 출력이 딸려 왔으니까요.

Claude Code가 테스트를 반드시 먼저 작성하게 강제하는 방법 (코드부터 짜지 않도록)

이게 가장 큰 골칫거리이고, 많은 팀이 며칠 만에 TDD를 접는 이유예요. Claude Code는 대부분의 AI 어시스턴트처럼 곧장 구현으로 뛰어들고 테스트는 보여주기용으로만 나중에 갖다 붙이는 경향이 있어요. "문제를 해결하라"고 훈련되어 있어서, AI에게는 테스트를 쓰는 것보다 코드를 쓰는 게 더 문제 해결처럼 보이거든요. 이 문제를 효과적으로 강제하는 장치가 세 가지 있어요:

1. 단계를 분리한 프롬프트. "함수 X와 그에 대한 테스트를 작성해줘"를 한 문장으로 묶지 마세요 — 그건 AI에게 코드부터 짜라는 초대장이에요. 확실히 쪼개세요. 레드 단계에서는 "X에 대한 실패하는 테스트를 작성하고, 아직 코드는 작성하지 마"라고만 말하고, 테스트가 레드가 된 뒤에야 그린으로 넘어가요. "아직 코드는 작성하지 마"를 대문자나 굵은 글씨로 넣으면 순응도가 눈에 띄게 좋아져요.

2. CLAUDE.md의 테스트 우선 규칙. 이게 가장 오래가는 방법이에요 — 규칙을 한 번만 써 두면 모든 세션에 적용돼요. 프로젝트의 CLAUDE.md 파일에 이 블록을 추가하세요:

## TDD rules (mandatory)
- Always write tests BEFORE the implementation for any new logic/function.
- Order: (1) write a failing test, (2) run `pytest -q` to confirm red,
 (3) write the minimal code to pass, (4) refactor while staying green.
- Do NOT write any implementation during the Red step.
- Do NOT edit tests just to make existing code pass.
- After every change, run the REAL tests and paste the output; never claim "it passes" on faith.

이 파일을 한 번도 설정해 본 적이 없다면, 탄탄한 CLAUDE.md 작성 가이드(테스트 우선 강제하기)를 참고하세요 — 프로젝트 전체의 규율을 켜고 끄는 스위치예요.

3. subagent를 이용한 단계 게이트. 고급 기법: 테스트 작성 전용 subagent를 사용하고 구현 계획을 보여주지 않는 거예요. "테스트 작성자"가 코드가 어떤 모습일지 모르면, 테스트는 여러분이 작성하려는 코드가 아니라 원하는 동작에 충실해져요 — 그러면 억지로 맞춰서 "그린으로 만드는" 테스트를 피할 수 있어요. 여러 에이전트를 단계별로 구성하는 방법은 brainstorm -> plan -> cook -> ship 워크플로에 있어요.

AI로 하는 TDD의 흔한 실수 (안티패턴)

AI로 하는 TDD는 매우 예측 가능한 방식으로 실패해요. "TDD를 하고 있다"고 스스로를 속이지 않도록 일찍 알아채세요:

안티패턴왜 잘못됐나어떻게 고치나
레드와 그린을 한 번에 하기AI가 먼저 코드를 짜고 그 코드에 맞는 테스트를 나중에 추가함 — 더 이상 테스트 우선이 아니고, 명세로서의 가치가 사라짐두 개의 별도 프롬프트로 나눔. 테스트가 레드인지 확인한 뒤에만 코드를 작성
기존 코드에 대해 AI에게 "테스트를 작성"하라고 요청하기그건 테스트 애프터이고, 현재 동작(버그 포함)을 고정할 뿐 설계를 이끌지 못함오래된 코드는: 바꾸기 전에 원하는 올바른 동작에 대한 테스트를 작성
검증 공백: AI가 테스트를 실행하지 않고 "완료"라고 보고하기AI는 실제로 실행하지 않고도 통과한 결과를 상상할 수 있음항상 실제 테스트 실행과 붙여넣은 출력을 요구. 계층을 쌓기: lint -> unit -> e2e
과도한 모킹너무 많이 모킹하면 테스트가 실제 로직이 아니라 목을 검사하게 됨I/O 경계(네트워크, DB)만 모킹하고, 순수 로직은 실제로 테스트
그냥 "그린을 위한" 형식적인 테스트assert True나 코드를 그대로 되풀이하는 테스트 — 무의미함모든 테스트는 엣지 케이스와 오류 케이스를 포함해, 하나의 구체적인 동작을 단언해야 함

이 중에서 검증 공백이 가장 위험해요. 조용히 진행되기 때문이죠. 레드로 남아 있는 테스트에서 막히거나 AI가 제자리를 맴돌 때, 테스트를 느슨하게 해서 "그린으로 만드는" 것을 허용하지 마세요 — 체계적인 디버깅으로 전환하고(AI로 디버깅하기 참고), 커밋하기 전에 AI 코드 리뷰를 한 번 돌려 변경의 품질을 확인하세요.

TDD 자동화하기: 단계 게이트를 강제하는 hook과 skill

수동 규율은 쉽게 흐트러져요. 단계 게이트가 여러분의 기억에 의존하지 않도록 자동화하는 방법이 두 가지 있어요:

테스트를 자동으로 실행하는 hook. Claude Code는 파일을 편집할 때마다 실행되는 hook을 지원해요. 편집할 때마다 pytest -q(또는 npm test, vitest run)를 실행하는 hook을 설정하면, 테스트가 레드가 되는 순간 hook이 즉시 표시해 주어서 AI는 다음으로 넘어가기 전에 고쳐야 해요. 이렇게 하면 "테스트 실행하는 걸 기억하기"가 "테스트 실행하는 걸 잊을 수 없기"로 바뀌어요.

프로세스가 내장된 skill/subagent. 프로젝트마다 테스트 우선 관례를 다시 쓰는 대신, 미리 만들어진 키트를 사용할 수 있어요.

미리 만들어진 키트로 속도를 높이세요: hook과 관례를 밑바닥부터 만들고 싶지 않다면, Claude Code용 AgentKit 키트(링크로 20% 할인)(agentkit.best, ak CLI — OpenAI의 AgentKit과 혼동하지 마세요)에는 코드 리뷰 워크플로를 포함해 60개 이상의 skill과 30개 이상의 워크플로가 엔지니어를 위해 들어 있어요. 이것들을 여러분의 레드-그린-리팩터 루프와 짝지으면, 수동 설정 없이 자동 단계 게이트와 리뷰를 얻을 수 있어요. 자세한 내용은 Engineer Kit 리뷰를 보세요. Engineer Kit은 현재 99달러예요(사이트에 반복 결제 언급은 없어요).

직접 만들든 키트를 쓰든, 원칙은 바뀌지 않아요. 테스트를 실행하고 결과를 보고하는 주체는 기계여야 해요 — AI가 스스로 선언하는 게 아니라요.

AI로 하는 TDD를 써야 할 때와 쓰지 말아야 할 때

AI로 하는 TDD는 만능 해결책이 아니에요. 어디서 빛나고 어디서 방해가 되는지 솔직해지세요:

쓸 때: 비즈니스 로직, 순수 함수(입력 -> 출력이 명확한 것), 데이터 처리, 백엔드 API, 그리고 특히 버그 수정이에요 — 버그를 재현하는 테스트를 작성하고(레드) 그것을 그린으로 고치는 것은 가장 깔끔한 버그 수정 워크플로예요. Claude Code로 백엔드 API를 구축할 때도 TDD가 가장 큰 효과를 내는 지점이 바로 여기예요. 엔드포인트 계약은 테스트로 고정하기 쉽거든요.

덜 맞을 때: 요건이 아직 흐릿한 탐색/프로토타입 단계(작성한 테스트가 끊임없이 삭제됨), UI 스타일링과 시각적 느낌(테스트는 비싸고 "보기 좋다/나쁘다"를 잡아낼 수 없음), 또는 일회용 스크립트예요. 요건이 아직 모호할 때 테스트 우선을 강제하면 속도만 느려져요 — 자유롭게 프로토타입을 만들고, 동작을 확정한 뒤에 돌아와서 남길 가치가 있는 부분에 테스트를 씌우세요.

자주 묻는 질문 (FAQ)

AI로 하는 TDD가 수동 TDD를 대체하나요?

원칙을 대체하는 게 아니라, 타이핑하는 사람만 바뀌어요. 테스트가 무엇을 검사하는지 정하고 그 테스트가 의미 있는지 판단하는 건 여전히 여러분의 몫이고, AI는 작성과 실행을 맡아요. 레드-그린-리팩터의 규율은 여전히 여러분의 것이에요.

Claude가 작성하는 테스트는 정확하고 완전한가요?

기본 케이스는 대체로 정확하지만, 엣지 케이스(빈 값, null, 음수, 유니코드, 네트워크 오류)를 놓치는 경우가 잦아요. AI가 작성한 테스트를 읽고, 신뢰하기 전에 엣지 케이스를 추가하라고 요청하세요. 테스트가 곧 명세이니, 그 명세를 승인하는 건 여러분이에요.

어떤 프레임워크 — pytest, Jest, Vitest?

프로젝트가 이미 쓰는 것을 쓰세요. Claude Code는 pytest(Python), Jest, Vitest(JS/TS)에 능숙해요. 중요한 건 AI가 아무거나 고르지 않도록 프롬프트나 CLAUDE.md에 프레임워크를 명시적으로 지정하는 거예요.

AI로 TDD를 하기 전에 테스트 작성법을 알아야 하나요?

기본은 알아야 해요. 테스트 작성에 뛰어날 필요는 없지만, AI가 작성한 테스트를 읽고 판단할 만큼은 필요해요 — 그렇지 않으면 무의미한 테스트에 승인을 내주게 돼요. TDD를 일하면서 자신의 테스트 실력을 끌어올리는 방법으로 여기세요.

AI가 작성한 테스트는 회귀를 막을 만큼 믿을 만한가요?

두 가지 조건 아래서 믿을 만해요: 여러분이 테스트를 리뷰했고, 테스트가 실제로 실행됐다는 것(AI가 스스로 통과를 선언한 게 아니라)이에요. AI가 너무 일찍 "완료"라고 보고하는 경향을 보완하려면 lint -> unit -> e2e 계층을 추가하세요.

레거시 프로젝트에 AI로 하는 TDD를 적용할 수 있나요?

가능하지만, 순서가 달라요. 레거시 코드는 먼저 현재 동작을 고정하는 "특성화 테스트(characterization tests)"를 작성한 다음 안전하게 리팩터해요. 오래된 프로젝트에 추가하는 완전히 새로운 기능은 여전히 평소대로 테스트 우선이에요.

결론과 다음 단계

AI로 하는 TDD는 결국 하나의 루프로 귀결돼요: 레드 테스트를 작성하고 -> Claude Code가 그것을 그린으로 만들게 하고 -> 그린을 유지하며 리팩터하고, AI의 말을 믿는 대신 항상 기계가 실제 테스트를 실행하게 하는 거예요. 핵심은 더 강력한 도구가 아니라, 단계를 분리한 프롬프트와 CLAUDE.md 규칙으로 AI가 테스트를 먼저 작성하도록 강제할 수 있는 거예요. 다음 단계: brainstorm -> plan -> cook -> ship 워크플로로 TDD를 완전한 프로세스에 연결하고, 올바른 방식의 바이브 코딩으로 프로세스의 토대를 다지세요.

지금 당장 더 강력한 Claude Code를 원하시나요? hook, 테스트 우선 관례, 코드 리뷰 워크플로를 직접 만드는 걸 건너뛰고 싶다면, engineer kit이 그 조각들을 묶어 여러분의 레드-그린-리팩터 루프에 바로 끼워 넣을 수 있게 해줘요.

AgentKit 가격 보기(링크로 20% 할인) ->

J

Jasmine

작성자 · Jasmine Daily

Jasmine Daily를 써 내려가는 사람 - 생각과 경험, 그리고 하루하루의 순간을 적어 두어요. 솔직하고, 서두르지 않고, 완벽하지 않게.

Jasmine Daily

아직 읽을 이야기가 더 있어요.

이 글이 마음에 닿았다면, 일기의 다른 페이지들도 몇 장 넘겨 보세요.

다음 읽을거리

관련 글