테스트 주도 개발은 테스트를 나중에 붙이는 습관이 아니라 설계 순서를 바꾸는 방식이다

테스트 주도 개발(TDD)은 기능 구현이 끝난 뒤 테스트를 붙이는 절차가 아니다. 켄트 벡이 정리한 방식대로라면, 먼저 실패하는 테스트를 쓰고, 그 테스트를 통과시키는 최소한의 코드를 만든 뒤, 마지막에 구조를 정리하는 순서를 반복하는 개발 방식이다. 흔히 레드-그린-리팩터링이라고 부르는 흐름이 바로 이것이다.
이 순서가 중요한 이유는 테스트가 품질 관리 도구인 동시에 설계 도구이기 때문이다. 먼저 테스트를 쓰면 “이 기능을 바깥에서 어떻게 사용할 것인가”를 코드보다 먼저 생각하게 된다. 즉 구현 세부보다 인터페이스와 기대 동작을 먼저 묻게 된다.
TDD의 핵심은 테스트 개수가 아니라 피드백 주기다
마틴 파울러는 테스트 주도 개발을 설명하면서 테스트를 조금 쓰고, 코드를 조금 쓰고, 다시 정리하는 짧은 순환을 강조한다. 여기서 중요한 것은 “테스트를 많이 확보했다”가 아니라, 설계와 검증 사이의 왕복 거리를 아주 짧게 유지하는 것이다.
이 방식이 주는 장점은 분명하다.
- 기능 요구를 더 작게 쪼개게 된다.
- 구현 전에 기대 결과를 먼저 적게 된다.
- 지나치게 큰 함수나 결합도 높은 구조를 빨리 눈치챌 수 있다.
테스트를 먼저 쓰려는데 너무 어렵다면, 그건 종종 코드 구조가 너무 많은 책임을 떠안고 있다는 신호이기도 하다.
”테스트 가능한 코드”는 대개 더 나은 경계선을 가진 코드다
TDD가 늘 옳다는 말은 아니다. 그래픽 연출, 감각 조정, 실험적인 프로토타입처럼 빠른 감각 확인이 더 중요한 영역도 있다. 하지만 게임 개발이든 일반 서비스 개발이든, 규칙이 명확한 계산 로직에는 TDD가 특히 잘 맞는다.
예를 들면 이런 부분이다.
- 피해량 계산
- 인벤토리 규칙
- 퀘스트 완료 조건
- 저장 데이터 변환
- 결제나 정산 로직
이런 로직은 “입력이 이러면 결과가 저래야 한다”는 문장으로 비교적 명확하게 표현할 수 있다. 그래서 테스트를 먼저 쓰는 순간 설계의 경계도 자연스럽게 잡힌다. 반대로 렌더링 품질, 애니메이션 손맛, 레벨 디자인 리듬처럼 감각 평가가 중심인 부분은 TDD만으로 다루기 어렵다.
리팩터링이 빠지면 TDD는 반쪽만 남는다
TDD를 “테스트 먼저 쓰기” 정도로만 이해하면 가장 중요한 부분을 놓치게 된다. 레드와 그린만 반복하면, 테스트는 통과하지만 구조는 계속 지저분해질 수 있다. 그래서 마지막 단계의 리팩터링이 빠지면 TDD는 설계를 개선하는 도구가 아니라 단지 체크리스트가 된다.
테스트가 있는 상태에서 리팩터링할 수 있다는 점이 핵심이다. 동작을 고정해 둔 뒤 내부 구조를 바꾸는 것이다. 이때 테스트는 “이 변경이 기존 동작을 깨뜨렸는가”를 빠르게 알려 주는 안전망이 된다.
읽기 쉬운 테스트가 좋은 설계를 밀어준다
파울러와 Cucumber 문서가 공통으로 보여 주는 지점은 테스트가 단지 개발자만 보는 코드가 아니라는 점이다. 주어진 상황-행동-결과(Given-When-Then) 식으로 테스트를 정리하면, 기능 요구를 설명하는 문장과 검증 코드의 거리가 줄어든다.
이런 방식은 테스트를 설명 문서처럼 읽히게 만든다. 테스트 이름이 잘 쓰여 있으면, 새로운 팀원이 코드를 처음 봐도 시스템이 무엇을 보장해야 하는지부터 파악할 수 있다.
핵심 정리
테스트 주도 개발은 테스트를 빨리 많이 쓰자는 운동이 아니다. 실패하는 테스트부터 시작해, 필요한 코드만 작성하고, 그다음 구조를 정리하는 방식으로 설계의 순서를 바꾸는 개발 방법이다.
그래서 TDD의 진짜 가치는 커버리지 숫자보다도, 더 작은 기능 단위, 더 분명한 경계선, 그리고 더 안전한 리팩터링에 있다. 테스트를 먼저 쓴다는 습관은 결국 “무엇을 만들 것인가”보다 “어떤 동작을 약속할 것인가”를 먼저 묻게 만든다.