[TDD] TDD 개발 방식이란?

최동근·2023년 1월 7일
0

TDD

목록 보기
4/4

안녕하세요 오늘은 TDD(Test Driven Development) 포스팅을 준비했습니다 🙆🏻
TDD를 본격적으로 알아보기 전에 단위 테스트에 대해 먼저 알아보겠습니다 🏃‍♀️

📌 단위 테스트(Unit Test) 란?

TDD 을 잘 따르냐의 판단 여부는 결국 단위 테스트를 잘 작성했느냐에 따라 달려있습니다 🔥

단위 테스트란 응용 프로그램에서 테스트 가능한 가장 작은 소프트웨어를 실행하여 예상대로 동작하는지 확인하는 테스트입니다.

✅ 단위 테스트를 작성해야 하는 이유

  • 코드를 수정하거나 기능을 추가할 때 수시로 빠르게 검증 할 수 있습니다.
  • 단위가 작기 때문에 리팩토링 시에 안정성을 확보할 수 있습니다.
  • 개발 및 테스팅에 대한 시간과 비용을 절감할 수 있습니다.

테스트 코드를 작성하면 우리가 작성한 코드들에 대해 수시로 빠르게 검증을 받을 수 있으며, 유지보수 및 리팩토링을 할 때에도 안정성을 확보할 수 있다는 장점이 있습니다.
하지만 그것보다 큰 장점으로 개발 및 테스팅에 대한 시간과 비용을 절감할 수 있다는 점에 주목해야 합니다 🙆🏻

우리는 개발이 끝난 뒤에 문제가 없는지 확인하기 위해 애플리케이션을 실행하고, 직접 수동 (통합) 테스트를 진행해야 합니다.
단위 테스트를 작성하지 않은 코드들은 테스트를 작성하지 않은 코드들 보다 버그가 있을 확률이 높은데, 문제는 직접 테스트 하는 비용이 너무 크다는 것입니다.
그 이유는 통합 테스트를 위해서는 캐시, 데이터베이스 등 외부 컴포넌트들과 연결 등 부가적인 시간이 필요하기 때문입니다 👨‍🔧

테스트 코드를 작성하지 않았다면 여러 개의 버그가 잠재되어 있을 확률이 있고, 모든 버그들을 수정하고 테스트를 반복하는 비용은 기하급수적으로 늘어나게 됩니다. 그러므로 우리는 개발 및 테스팅에 대한 비용을 줄이기 위해 단위 테스트를 작성해야 합니다 💡

단위 테스트의 개념과 장점에 대해 알아보았습니다 🙆🏻
그러면 개발시에 단위 테스트가 왜 권장될까요?
답은 단위 테스트가 좋은 테스트 조건에 부합하기 때문입니다 👍

📌 좋은 테스트란?

해당 내용은 CleanCode에 있는 내용을 참고했습니다.

  • Fast : 테스트는 빠르게 동작하여 자주 실행 가능해야 한다.

  • Independent : 각 테스트는 독립적이며 서로 의존해서는 안된다.

  • Repeatable : 어느 환경에서도 반복 가능해야 한다.

  • Self-Validating : 테스트는 성공 또는 실패로 결정되어 자체적으로 검증 가능해야 한다.

  • Timely : 테스트는 적시에, 실제 프로덕션 코드를 구현하기 직전에 구현해야 한다.

이처럼 좋은 테스트는 5가지 조건을 지키는 테스트 코드 작성으로 실현됩니다.
여기서 저희가 주목해야하는 규칙은 'Timely' 입니다.
이렇게 실제 코드를 구현하기 직전에 테스트 코드를 먼저 작성하는 개발 방법론을 TDD 라고 합니다. TDD 에 대해 좀더 알아보겠습니다 ✏️

📌 TDD 란?

TDD 란 Test Driven Development의 약자로 '테스트 주도 개발' 이라고 합니다.
반복 테스트를 이용한 소프트웨어 방법론으로 "작은 단위의 테스트 케이스를 작성하고 이를 통과하는 코드를 추가하는 단계를 반복하여 구현합니다" 👨‍💻

짧은 개발 주기의 반복에 의존하는 개발 프로세스이며, 애자일 방법론 중 하나인 eXtream Programming(XP)의 ‘Test-First’ 개념에 기반을 둔 단순한 설계를 중요시합니다.

TDD에서는 제품의 기능 구현을 위한 코드(구현체 혹은 프로덕션 코드)와 별개로, 해당 기능이 정상적으로 움직이는지 검증하기 위한 테스트 코드를 작성합니다.
이때 테스트 코드는 단위 테스트 기반으로 작성합니다 🔨
테스트가 실패할 경우, 테스트를 통과하기 위한 최소한으로 코드를 개선합니다. 이후 최종적으로 테스트에 성공한 코드를 리팩토링 하는 과정을 거칩니다 🙆🏻

📌 TDD 개발 방식 주기

해당 이미지는 [TDD 개발주기] 를 표현한 것입니다.

  • [RED] : 실패하는 테스트 코드를 먼저 작성합니다.
    TDD 개발에서의 첫번째 단계는 실패입니다.
    즉, 실패하는 테스트 케이스를 작성하는 것입니다. 이때 테스트 케이스는 프로젝트 전체의 모든 기능에 대해서
    모든 케이스를 작성하는 것이 아니라, 먼저 구현할 기능에 대해서 테스트 케이스를 하나씩 작성하는 것입니다.

  • [Green] : 테스트 코드를 성공시키기 위한 실제 코드를 작성합니다.
    두번째 단계는 성공입니다.
    실패 단계에서 작성한 테스트 케이스를 통과시키기 위한 최소한의 코드를 작성하는 단계입니다.

  • [Blue] : 중복 코드 제거, 일반화 등의 리팩토링을 수행합니다.
    세번째 단계는 리팩토링 단계입니다.
    성공 단계에서 작성한 코드에 중복되는 코드나, 개선시킨 방법이 있다면 리팩토링을 진행해줍니다.

✅ 일반 개발 방식과 TDD 개발 방식의 비교

보통 개발 방식은 아래와 같은 개발 주기를 갖습니다 🤔

이러한 방식은 소프트웨어 개발을 느리게 하는 잠재적 위험이 존재합니다.

위와 같은 방식이 전형적인 TDD 방식입니다.
이러한 반복적인 단계가 진행되면서 자연스럽게 코드의 버그가 줄어들고 소스코드가 간결해집니다 🧑🏼‍💻

📌 Spring 에서 TDD 프로그래밍 방법

  • Repository -> Service -> Controller 순서로 개발을 진행합니다.
  • Repository 계층의 테스트는 H2와 같은 인메모리 데이터베이스 기반의 통합 테스트로 진행합니다.
  • Service 계층의 테스트는 Mockito를 사용해서 진행합니다.
  • Controller 계층의 테스트는 SpringTest의 MockMvc 를 사용해서 진행합니다.

Repository부터 계층을 작성해야 TDD의 flow가 매끄럽게 진행이 되는 것 같습니다.
왜냐하면 Repository 계층은 다른 계층에 대한 의존성이 거의 없기 때문에 먼저 작성하기가 편리하기 때문이죠.
Service 계층은 Repository에 의존하기 때문에 Repository가 있어야 개발이 편리하며 흐름이 끊기지 않고, Controller 계층은 마찬가지로 Service계층에 의존하기 때문입니다.

반대로 Controller부터 개발을 진행하면 Controller를 작성하다가 Service를 작성하고 그러다가 Repository 까지 내려가서 흐름이 끊길 수 있기 때문입니다.
만약 Controller부터 하는게 편하다면 Controller부터 개발해도 전혀 문제가 없습니다.
해당 방법은 정해진 답이 있는 것이 아니므로, 개인에 맞게 맞춰나가면 됩니다 😄

📌 TDD 개발 방식 장점 및 단점

✅ TDD 개발 방식 장점

1) 객체지향적인 코드 개발

태스트 코드를 먼저 작성한다면 명확한 기능과 구조를 설계할 수 있게 됩니다.
또한 테스트의 용이성을 위해 복잡한 기능들을 하나의 함수에 모두 구현할 경우 테스트 방식이 복잡해지고 시간이 오래 걸리며
수정이 되는 경우 테스트 코드를 재 사용 할 수 없게됩니다.
따라서 TDD 프로세스를 따르는 코드의 경우에는 재사용성을 고려하며 작성하게 됩니다.

2) 설게 수정 시간의 단축
TDD 프로세스는 일반 개발 방식과는 달리 테스트 코드를 먼저 작성하고 테스트를 진행하기 때문에 설계의 구조적인 문제를 바로 찾아낼 수 있습니다. 문제를 발견했다면 피드백을 주고 받으며 수정을 하고 추가로 다시 테스트를 진행하게 됩니다.
따라서 개발이 완료된 시점에서 설계의 문제점을 발견하고 설계를 수정한 뒤 코드 전체를 수정하는 상황을 겪지 않아도 됩니다.

3) 디버깅 시간의 단축
TDD 프로세스는 단위 테스트 기반으로 진행되기 때문에, 프로그램에 문제가 발생하였을 때에도 각각의 모듈 별로 테스트를 진행해보면 문제를 쉽게 찾아낼 수 있습니다.
만약 일반 개발 방식이였다면, 버그를 찾기 위해서 프로그램 전체 코드를 봐야할 수도 있는데 프로그램이 큰 경우 여러 영역에 걸쳐 전체 코드를 검토하는 것이 쉽지 않습니다.

4) 유지 보수의 용이성
개발이 완료된 시점에서 어떠한 기능을 추가하거나 수정하는 경우에 가장 고려되는 부분이 수정하거나 추가한 코드가 전체 프로그램에 어떠한 영향을 미칠지 모른다는 점입니다.
단순한 기능의 수정 혹은 추가도 전체 프로그램에 큰 영향을 끼칠 수가 있습니다.
따라서 이러한 경우 모든 기능들을 처음부터 다시 테스트 해야 합니다.
그러나 TDD 프로세스에 경우 자동화된 유닛 테스팅을 전제하므로 이렇게 전체를 테스트 하는 시간을 단축시킬 수 있습니다.

5) 테스트 문서의 대체 기능
일반 개발 방식은 테스트를 진행했더라도 단순 통합 테스트에 지나지 않습니다.
하지만 TDD 를 통해 테스팅을 자동화시키면서 정확한 테스트 근거를 산출해 정의서를 작성할 수 있습니다.

✅ TDD 개발 방식 단점

1) 사전준비 기간

TDD 개발 방식을 실제 사용하는 것은 쉽지 않습니다 🤔
보통 개발자를 준비하는 사람들은 대다수가 TDD 에 익숙하지 않을 것 입니다. 처음부터 TDD 개발 방식을 배우지는 않죠?
실제 저도 현재까지 TDD 사용법이 낯설게 느껴질 때가 많습니다.
TDD 를 정확하고 효율적으로 사용하기에는 오랜 시간이 걸리는 것 같습니다.

2) 생산성 저하

프로젝트를 진행할 때 지난 경험을 통해 어떤 결과가 나올지 눈에 뻔히 보이는 경우가 있습니다.
이는 보통 개발중에 바로 인지 가능한데, TDD 개발 방식은 이러한 부분까지 테스트 코드를 작성해야 합니다.
하지만 TDD 개발방식을 통해 개발자가 "이건 무조건 이런 결과가 나올꺼야" 라고 예측한 결과가 혹시 다를수도 있을 가능성에 대해 안정성을 보장할 수 있습니다.

📌 마무리

이렇게 TDD에 대해 전반적으로 알아보았습니다 👼
하지만 TDD는 더욱히 개념과 실제 응용은 다른 문제라고 생각합니다.
저 또한 개념만 숙지한체 프로젝트에서 TDD 를 적용하는 것이 매우 힘들었고 매번 괴리감을 느꼈습니다.
따라서 TDD 응용에 대한 포스팅을 제작할 계획입니다.
TDD 개발 방식 적용기 #1 를 참고헤주세요!

참고

TDD 단위 테스트와 TDD 개발 방식 소개
테스트 주도 개발

profile
비즈니스가치를추구하는개발자

0개의 댓글