카테고리 없음

[고찰] TDD에 대한 고찰

tally 2025. 5. 3. 22:35

개요

TDD(Test-Driven Development)는 보통 Red(실패하는 테스트 작성) → Green(통과하는 최소 구현) → Blue(리팩터링)이라는 사이클로 설명됩니다.
이 설명이 틀리지 않지만 제가 개발을 하며 체감한 TDD는 단순한 반복 루틴 이상의 의미를 가집니다.
짧은 경력이지만 저는 TDD가 요구사항을 탐색하고, 설계를 정제해가는 데 도움을 주는 사고 중심의 개발 방식이라는 점을 더 크게 느꼈습니다.
 
이 글에서는 제가 고민했던 좋은 테스트란 무엇인가, 그리고 왜 TDD인가에 대한 개인적인 생각을 정리해보고자 합니다.
 
 

좋은 테스트란

제가 생각하는 좋은 테스트는 코드 변경 이후에도 기존 기능이 망가지지 않았다는 신뢰를 줄 수 있는 테스트입니다. 또한 가능하다면 내부 구현에 의존(화이트박스 테스트)하기보다 동작 결과를 기준으로 검증하는 블랙박스 테스트에 가까운 형태가 되어야 한다고 생각합니다.
 
단위 테스트라는 책으로 스터디하며 '기존 기능이 망가지지 않음을 신뢰할 수 있다'는 테스트 특성을 회귀 방지(Regression Prevention)라고 표현한다는 것을 알게 되었습니다.
처음에는 회귀라는 단어와 그에 대한 설명이 다소 어렵게 느껴지고 이 용어의 의미에 대한 토론을 나누었지만, 결국 핵심은 코드 수정이후에도 기존 시스템이 잘 동작하는지 감지해낼 수 있는가를 의미했습니다.
즉, 테스트는 단지 코드를 확인하는 수단이 아니라 코드 변경에 대한 신뢰를 제공하는 도구여야 한다는 뜻이었습니다.
 
이 책에서는 좋은 (단위) 테스트가 가져야 할 4가지 기준을 다음과 같이 정리하고 있습니다

  • 회귀 방지
  • 빠른 피드백
  • 유지보수성
  • 리팩터링 내성

이 중에서 빠른 피드백과 유지보수성은 레퍼런스나 LLM과 같은 도구의 도움을 받아 어느 정도 보완이 가능한 요소라고 느끼고 있습니다. 
반면, 리팩터링 내성은 여전히 어렵지만 저는 테스트 대상이 적절히 식별되어 있고, 블랙박스 테스트에 가깝게 작성되었다면 어느 정도는 리팩터링에 내성을 가진 테스트를 만들 수 있다고 느껴졌습니다. 그리고 테스트 코드가 실제 리팩터링의 대상이 될 정도로 구조가 바뀌었다면 기존 테스트를 유지하려고 억지로 수정하기보다 새로운 코드 구조에 맞게 테스트를 새로 작성하는 것이 더 맞는 방향이라고 생각하고 있습니다.
 
이러한 의미에서 자주 이야기되는 private 메서드는 테스트 대상이 되어서는 안 된다고 생각합니다.
만약 private 메서드가 테스트 대상이 되어야 할만큼 중요하다면 테스트 우회 방법(접근 제어자를 변경하거나 리플렉션을 사용 등)을 고민하기보다 설계적으로 외부로 분리하고 공개 가능한 형태로 바꾸는 것이 바람직한 방향이라고 느꼈습니다.
 
 

TDD와 좋은 테스트

이처럼 좋은 테스트에 대한 고민을 이어가다보니 TDD의 본질에 대해서 다시 생각해보게 되었습니다.
처음엔 TDD를 단순히 테스트를 먼저 작성하는 방식이라고만 알고 있었지만 지금은 좋은 테스트를 기반으로 사고의 흐름을 명확히 하고, 결과적으로 더 나은 설계를 이끌어내는 도구로 바라보게 되었습니다.
 
테스트를 처음 배울 당시에는 프로덕션 코드를 먼저 작성하고 테스트를 나중에 작성하는 방식으로 접근했었습니다.
그런데 돌이켜보면 이 방식이 테스트 커버리지만을 고려하게 되거나, 가치가 낮은 테스트 대상(중요한 기능이 아닌)에 시간과 에너지를 쓰곤 했던 기억이 납니다.
 
TDD는 Red → Green → Blue 사이클을 따라 실패하는 테스트(Assert)를 먼저 작성하고, 그 테스트를 통과시키기 위한 최소한의 코드를 구현한 후, 리팩터링을 진행합니다. 이 과정은 무엇을 테스트할 것인가를 만족시켜야 할 인수 조건부터 사고를 시작하는 방식으로 이어지게 됩니다.
그 덕분에 단순히 동작 여부가 아닌, 기능이 왜 필요한가, 무엇을 보장해야 하는가를 먼저 고민할 수 있습니다.
 
 

요구사항 정의와 문제 정의

최근 들어 제가 가장 많이 고민하고 노력하는 부분은 기술적 구현보다도 문제를 잘 정의하는 것과 요구사항의 본질을 잘 이해하려고 하는 것입니다.

  • 이게 진짜 해결해야 할 문제일까?
  • 사용자나 비즈니스 관점에서 꼭 필요한 기능일까?
  • 임팩트가 적은 영역에 너무 많은 시간을 쓰고 있는 건 아닐까?

가끔은 우리가 알아차리지 못하는 숨겨진 비즈니스 요구사항이 존재하기도 합니다. 
 
검증문(Assert)부터 출발하는 TDD는 단순한 기능 검증이 아니라 왜 이 동작이 필요한가?를 먼저 고민하게 만들어 테스트 코드를 요구사항 명세서처럼 활용할 수 있는 흐름으로 가이드하는 역할을 합니다.
 
 

결론

사실 저도 아직은 TDD를 완벽하게 실천하고 있지는 못합니다.
여전히 프로덕션 코드를 먼저 작성하고, 나중에 테스트를 작성하는 경우도 많습니다.
하지만 그럼에도 불구하고 TDD를 접하고 실천해보며 얻은 경험은 분명한 가치가 있었습니다.

  • 의미 있는 테스트 대상을 식별하게 해준다.
  • 요구사항 중심의 사고 흐름을 도와준다.

 
끝으로 여담이지만, 각자의 역할을 가진 GPT를 만들어 질문을 주고받는 것도 많은 도움이 되었습니다.
제 경우에는 세 개의 역할군(CEO: ROI가 적절한지, TPM: 요구사항, 인수조건, 유저스토리 도출, CTO: 시스템 설계)을 만들어 질문을 주고받으며 도움을 받고 있습니다.

 
 
 
작성 시간
5시간 22분
 
 
참고