단위 테스트는 모든 코드에 동일한 가치로 적용되지 않습니다.
코드의 복잡도와 도메인 유의성, 협력자 수에 따라 테스트 전략을 달리해야 진정한 효율이 나옵니다.
이 글에서는 코드의 구조에 따른 테스트 유의성과 아키텍처 패턴을 바탕으로, 테스트 전략을 정리해보았습니다.
코드 복잡도와 도메인 유의성
- 코드 복잡도는 코드 내 의사 결정 지점의 수에 따라 결정됩니다.
이 지점은 명시적으로 드러나기도 하고, 라이브러리 등 외부 요소를 통해 암시적으로 존재하기도 합니다. - 도메인 유의성은 해당 코드가 비즈니스 문제 해결에 얼마나 중요한지를 나타냅니다.
복잡한 코드가 도메인 유의성이 높을 가능성이 크지만, 항상 그런 것은 아닙니다.
복잡하거나 도메인 유의성이 높은 코드는 단위 테스트를 통해 회귀 방지 효과를 크게 얻을 수 있습니다.
테스트 전략에 영향을 주는 요소: 협력자 수
협력자가 많은 코드는 테스트 준비 과정(Stub/Mock 등)에서 비용이 큽니다.
예상 상태로 협력자를 구성한 뒤, 상호 작용을 검증해야 하므로 코드의 공간과 유지 비용이 늘어납니다.
코드의 네 가지 유형과 테스트 전략
| 유형 | 특징 | 테스트 전략 |
| 도메인 모델 / 알고리즘 | 복잡하거나 도메인 유의성 높음, 협력자 거의 없음 | 단위 테스트 가장 유리 |
| 간단한 코드 | 복잡도 낮고 유의성 낮음, 협력자 없음 | 테스트 필요 없음 |
| 컨트롤러 | 복잡도/유의성 낮음, 협력자 많음 | 통합 테스트 권장 |
| 지나치게 복잡한 코드 | 복잡도 높고 협력자 많음 | 코드 분할 필요 |
코드가 중요하거나 복잡할수록, 협력자는 적을수록 단위 테스트에 유리합니다.
험블 객체 패턴과 아키텍처
험블 객체 패턴은 비즈니스 로직을 별도의 클래스로 추출해 테스트 용이성을 확보하는 전략입니다.
이때 컨트롤러는 단순히 해당 객체를 호출하는 얇은 래퍼로 구성됩니다.
관련 아키텍처
| 아키텍처 |
설명 |
| 육각형 아키텍처 | 비즈니스 로직과 외부 의존성(입출력, DB 등)을 분리 |
| 함수형 아키텍처 | 외부 의존성뿐 아니라 모든 협력자와도 완전히 분리 |
코드의 깊이와 너비
- 깊이: 코드의 복잡성 혹은 도메인 유의성
- 너비: 협력자의 수
한 코드는 깊거나 넓을 수는 있지만, 깊고 넓은 코드는 피해야 합니다.
테스트 유의성과 설계 트레이드오프
코드 분리 시 세 가지 특성 중 동시에 두 개까지만 가질 수 있습니다.
| 특성 | 설명 |
| 도메인 모델 테스트 유의성 | 협력자 수가 적어 테스트하기 쉬움 |
| 컨트롤러 단순성 | 비즈니스 결정이 없고, 호출만 수행 |
| 성능 | 외부 의존성 호출을 최소화 (DB, API 등) |
| 선택 | 장점 | 단점 |
| 외부 의존성은 컨트롤러에서 호출 | 도메인 모델 테스트 용이 + 컨트롤러 단순 | 성능 저하 |
| 도메인 모델에 외부 의존성 주입 | 컨트롤러 단순 + 성능 확보 | 테스트 유의성 떨어짐 |
| 로직 세분화 | 성능 + 테스트 유의성 확보 | 컨트롤러 복잡도 증가 |
컨트롤러 복잡도 완화를 위한 패턴
- CanExecute/Execute 패턴
- canDo() 메서드를 do() 전에 반드시 호출하도록 유도
- 전제 조건 확인을 도메인 모델 내부로 이동
- 컨트롤러의 의사결정 제거
- 도메인 이벤트 패턴
- 도메인 내부에서 중요한 변경을 이벤트로 발행
- 외부 프로세스 호출 책임은 컨트롤러가 아닌 이벤트 핸들러가 가짐
테스트 전략의 핵심 철학
“추상화할 것을 테스트하기보다는, 추상화를 테스트하는 것이 더 쉽다.”
- 도메인 이벤트는 외부 호출 위의 추상화
- 도메인 모델은 데이터 저장소에 대한 추상화
→ 즉, 비즈니스 로직을 감싸는 추상화 계층을 테스트하면 테스트 비용이 줄고 유지보수가 쉬워집니다.
마무리
단위 테스트의 효율은 코드의 복잡도, 도메인 유의성, 협력자 수의 조합으로 결정됩니다.
복잡한 비즈니스 로직은 외부 의존성 없이 모델 내부에서 테스트 가능해야 하며, 컨트롤러는 단순하게 유지할수록 좋습니다.
적절한 아키텍처 분리와 테스트 전략 선택은 유지보수성과 품질 향상의 핵심입니다.
'기타' 카테고리의 다른 글
| [단위테스트] 원칙과 패턴 (9장) - 목 처리에 대한 모범 사례 (0) | 2025.04.22 |
|---|---|
| [단위테스트] 원칙과 패턴 (8장) - 통합 테스트를 하는 이유 (0) | 2025.04.21 |
| [단위 테스트] 원칙과 패턴 (6장) - 단위 테스트 스타일 (0) | 2025.04.17 |
| [단위 테스트] 원칙과 패턴 (5장) - 목과 테스트 취약성 (0) | 2025.04.16 |
| [단위 테스트] 원칙과 패턴 (4장) - 좋은 단위 테스트의 4대 요소 (0) | 2025.04.15 |
