🥔TDD란 무엇인가
- TDD(Test-Driven Development)는 테스트 주도 개발 방법론이다.
- 테스트를 먼저 작성하고, 해당 테스트를 통과하는 코드를 나중에 작성한다.
- 테스트가 개발을 이끄는 방식이다.
🥔기본 개념
일반적인 개발 방식
1. 코드를 작성한다
2. 실행해서 테스트한다
3. 버그를 발견한다
4. 수정한다
5. 이를 반복한다
TDD 방식
1. 실패하는 테스트를 작성한다
2. 테스트를 통과할 최소한의 코드를 작성한다
3. 코드를 리팩토링한다
4. 이를 반복한다
🥔TDD의 핵심 사이클: Red–Green–Refactor
🔴 Red
- 실패하는 테스트를 먼저 작성한다.
- 실행하면 테스트가 실패한다.
- 아직 기능이 구현되지 않은 상태다.
🟢 Green
- 테스트를 통과할 최소한의 코드만 작성한다.
- 테스트가 성공한다.
🔵 Refactor
- 중복을 제거하고 구조를 개선한다.
- 테스트는 계속 통과해야 한다.
🥔실제 예시
계산기 기능 구현
Red: 실패하는 테스트 작성
import unittest
from calculator import Calculator
class TestCalculator(unittest.TestCase):
def test_add(self):
calc = Calculator()
result = calc.add(2, 3)
self.assertEqual(result, 5)
- 테스트 실행 시 실패한다.
- Calculator 클래스가 존재하지 않는다.
Green: 최소한의 코드 작성
class Calculator:
def add(self, a, b):
return a + b
Refactor: 코드 개선
class Calculator:
def add(self, a: int, b: int) -> int:
return a + b
다음 기능도 같은 방식으로 반복한다
- 테스트 작성 → 실패
- 기능 구현 → 성공
- 리팩토링 수행
🥔언리얼 엔진에서의 TDD 예시
데미지 시스템 테스트
Red: 테스트 작성
TestEqual("HP should be 70", ResultHP, 70.0f);
Green: 기능 구현
float ApplyDamage(float CurrentHP, float Damage)
{
return CurrentHP - Damage;
}
Refactor: 예외 처리 추가
float ApplyDamage(float CurrentHP, float Damage)
{
float NewHP = CurrentHP - Damage;
return FMath::Max(0.0f, NewHP);
}
🥔TDD의 장점
버그를 조기에 발견한다
- 요구사항이 테스트로 명확해진다.
- 문제를 즉시 확인한다.
테스트 코드가 문서 역할을 한다
리팩토링이 안전하다
설계 품질이 좋아진다
- 의존성이 분리된다.
- 단일 책임 원칙을 지키게 된다.
- 모듈화가 자연스럽게 이루어진다.
코드 수정에 대한 자신감이 생긴다
🥔TDD의 단점
초기 개발 속도가 느리다
- 테스트 작성에 시간이 든다.
- 장기적으로는 유지보수 비용이 줄어든다.
학습 곡선이 존재한다
모든 코드에 적합하지 않다
- UI, 그래픽, 감성 요소는 테스트가 어렵다.
- 게임 밸런스는 플레이 테스트가 필요하다.
과도한 테스트는 오히려 부담이 된다
- 단순 getter/setter 테스트는 유지보수를 어렵게 만든다.
🥔TDD와 일반 테스트의 차이
| 구분 | TDD | 일반 테스트 |
|---|
| 작성 순서 | 테스트 먼저 | 코드 먼저 |
| 목적 | 개발 가이드 | 결과 검증 |
| 테스트 범위 | 넓음 | 제한적 |
| 설계 영향 | 큼 | 적음 |
| 리팩토링 | 안전함 | 위험할 수 있음 |
🥔실전 적용 팁
TDD가 효과적인 경우
- 복잡한 비즈니스 로직이다.
- 수학 계산과 알고리즘이다.
- 데이터 변환과 파싱 로직이다.
- API와 네트워크 처리다.
- 게임 규칙과 전투 시스템이다.
TDD가 어려운 경우
- UI와 UX 영역이다.
- 그래픽과 렌더링이다.
- 빠른 프로토타입 단계다.
- 테스트가 없는 레거시 코드다.
하이브리드 접근
- 핵심 로직은 TDD로 개발한다.
- UI와 그래픽은 수동 테스트를 사용한다.
- 프로토타입은 빠르게 만든 뒤 테스트를 추가한다.
🥔CI/CD와 결합한 TDD 흐름
1. 로컬에서 TDD로 개발한다
2. Git에 push한다
3. Jenkins가 자동 빌드를 수행한다
4. 모든 테스트를 실행한다
5. 실패 시 알림을 전송한다
6. 성공 시 배포한다
🥔TDD의 3가지 원칙
1. 실패하는 테스트 없이는 코드를 작성하지 않는다
2. 필요한 만큼만 테스트를 작성한다
3. 테스트를 통과할 만큼만 코드를 작성한다
🥔요약
- TDD는 테스트를 먼저 작성하고 테스트를 통과하는 코드를 나중에 작성하는 개발 방식이다.
🔴 Red: 실패하는 테스트 작성
🟢 Green: 테스트 통과 코드 작성
🔵 Refactor: 코드 개선
- 버그를 줄인다.
- 리팩토링이 안전해진다.
- 설계 품질이 향상된다.
- 초기 비용은 있지만 장기적으로 효율적이다.