TDD란 무엇이며 왜 필요한가?
TDD (Test-driven development)의 이야기는 개발자라면 한번쯤 들어본 이야기다.
하지만 막상 이에 대해 ‘왜 해야 되는가?’에 대해 물음을 가져본다면 적어도 솔직히 나는 명확하게 설명할 자신이 없었다.
이 글은 TDD에 대해 알아보는 것과 동시에 위에 대한 물음에 대해 답을 찾아나가는 과정을 정리한 글이다.
해당 글은 아래와 같은 순서로 진행된다.
1. TDD에 대한 요약
2. TDD의 장점 및 단점
3. TDD의 종류 및 설명
TDD에 대한 요약
TDD(Test-driven devlopment)의 의미는 무엇인가?
TDD는 개발 방법론 중 하나로 테스트가 전체 개발을 주도해 내가는 것을 말한다.
즉, 비지니스 코드를 먼저 작성하는 것이 아닌 테스트가 중심이 되어 전체 개발 방향을 이끌고 나가는 것이다.
위키에서는 아래와 같이 TDD에 대해서 설명하고 있다.
테스트 주도 개발(Test-driven development TDD)은 매우 짧은 개발 사이클을 반복하는 소프트웨어 개발 프로세스 중 하나이다. 개발자는 먼저 요구사항을 검증하는 자동화된 테스트 케이스를 작성한다. 그런 후에, 그 테스트 케이스를 통과하기 위한 최소한의 코드를 생성한다. 마지막으로 작성한 코드를 표준에 맞도록 리팩토링한다.
기존에 비지니스 코드 중심의 개발과 테스트 주도 개발의 차이점은 아래와 같다.
뭐든지 개념만을 들으면 추상적이기 마련이다. 우선 TDD란 이런것이다 정도로만 인지를 하고 이 글의 세번째에 해당하는 TDD의종류와 방법에 설명할 때 좀 더 자세히 살펴 보도록 하자
TDD의 장점 및 단점
TDD에 대해서 무엇인지는 감이 오는데 그럼 왜 해야되는가?
그 필요성에 대한 의문은 TDD의 장점을 본다면 자연스럽게 답을 구할 수 있을 것이라고 본다.
하지만 언제든 장(長)이 있으면 단(點)이 있기 마련이다.
장점과 함께 TDD를 진행할 때 유의해야 될 점에 대해서도 함께 보도록 하자.
장점
- 코드를 작성하기전 설계에 대해 구체적으로 작성이 가능하다.
모든 개발자들이 코드를 작성하기 전 나름대로의 생각을 바탕으로 비지니스 코드를 만들어 낸다.
누군가는 그 설계를 종이에 글로 끄적이기도 하며, 또는 그림으로 심지어 코드를 작성하면서 동시에 설계에 대해 생각하기도 한다.
설계는 개발에 있어 매우 중요하며 잘못된 설계는 잘못된 동작을 만들어 내며 이를 고치기 위한 시간을 소모하는 것은 비용이 발생하는 것이다.
때문에 경험 많은 개발자분들이 늘 코드를 작성하기 위해 무엇을 만들지 생각을 하고 만들어라고 조언 해주시고는 한다.
TDD는 이러한 설계를 강제하게 만들며 보다 구체적으로 동작에 대해 서술 함으로써 내가 무엇을 만들어야 하는지 어떤 기능을 만들어야 하는지 명확하게 파악할 수 있다.
시간은 곧 비용이다.
우리는 보다 체계적인 설계를 만들어 나갈 의무가 있다.
2. 오류에 대해 신속한 파악이 가능하며, 디버깅 시간을 단축시킨다.
프로젝트의 규모가 커지면 커질수록 복잡성은 늘어난다.
많은 개발자가 참여할 수록 본인이 담당하는 부분 외에 알 수 없는 부분이 늘어나며 자신의 코드 수정이 다른 부분에 까지 영향을 미칠 수 있다.
규모가 큰 프로젝트 일수록 이를 사람이 일일히 테스트 하는 것은 힘들어지며 그 원인을 찾아내는 것 역시 쉬운 일이 아니다.
잘못된 코드에 대한 의존성이 커질 수록, 더욱이 나쁜 사이드 이펙트를 발생시키고 있다면 문제는 심각해진다.
이미 복잡성성이 늘어 났을 때 이에 대한 코드를 고치는 것보다 코드를 작성한 당시 바로 고치는 것이 비용이 더 적게 드는 것은 당연한 것이다.
결함은 일찍 찾을 수록 고치는 비용이 적게 든다.
테스트 코드를는 이에 대해 어떤 부분이 어디까지 통과를 했는지 어느 부분에 문제가 발생했는지 명확하게 알 수 있으므로 신속한 파악이 가능하다.
이는 디버깅 시간의 단축으로 보다 안정적으로 프로젝트를 진행 할 수 있게 된다.
3. 문서의 대체 가능
우리는 코드를 읽다 보면 때론 무슨 의미인지 모를때가 있다.
물론 읽기 쉬운 코드를 작성하는 것이 첫번째 이지만 현실을 볼때 이를 지키지 못하는 경우가 있다.
이를 위해 주석을 다는 경우도 있고 해당 코드를 작성한 사람을 찾아가거나 또는 작성한 문서를 보고는 한다.
테스트 코드는 설계를 할 당시에 어떤 의도를 가지고 작성되었는지 그리고 어떤 결과 값이 나오길 기대하는지를 적기 때문에 코드를 쓴 사람의 의도를 충분히 파악할 수 있다.
테스트 코드는 이와 같이 문서의 기능을 대체 한다.
이외에도 장점이 많겠지만 개인적으로는 위의 3개의 부분이 TDD를 진행 하는 핵심적인 이유라고 생각한다.
단점
- 단기적으로 봤을때 테스트 코드를 작성하는 시간이 소모된다.
이는 테스트 코드를 작성하는데 있어 개발자 개인이 익숙하지 않을 수록 소모되는 시간이 커진다고 생각한다.
기존에 비지니스 코드만 설계하고 넘어갔을 때에 비해 테스트 주도 개발은 별도의 테스트 케이스를 작성해야 하므로 절대적인 시간이 늘어난다.
하지만 장기적으로 봤을때는 위의 장점에서 언급했듯이 개발 진행에 있어서의 전체적인 시간을 축소시키며 이는 효율의 향상으로 이어진다.
어디까지나 이는 테스트 코드 작성이 익숙하지 않음을 전제로 하며 TDD를 훈련 했을시 해결 가능한 부분이라고 본다.
2. 100%의 안정성을 보장해주지는 않는다.
TDD는 어디까지 개발자가 설계한 예상 가능한 예측값과 환경을 기반으로 한다.
예를 들어 외부 의존성이 가지고 있는 오류, 네트워크의 문제, 하드웨어의 문제등
설계한 요소 외에 대한 부분은 리스크를 가져갈 수 밖에 없으며 이는 테스트 코드에 대해 100% 안전하다고 여길 수 없음을 의미한다.
TDD의 종류 및 설명
자동화 테스트는 일반적으로 아래와 같은 범주로 나뉜다.
- A Unit test [단위 테스트]
- A Widget (or Component) test [컴포넌트 테스트]
- An Integration test [통합 테스트]
A Unit test [단위 테스트]
단일 함수 또는 클래스를 테스트 하는 것으로 코드의 논리 단위의 정확성을 확인하는 것을 목표로 한다.
예를 들어 다음과 같은 것들은 단위 테스트에 포함되지 않는다.
디스크에 쓰고 읽는 것, 화면에 렌더링 되는것, 테스트가 실행되는 프로세스 외부에서 사용자의 입력을 외부에서 받는 것
A Widget (or component) test [컴포넌트 테스트]
하나의 컴포넌트 또는 위젯을 테스트 하는 것으로 UI를 테스트 하는 것에 속한다. 해당 테스트는 위젯의 UI가 예상대로 보이고 상호작용을 확인하는 것을 목표로 한다.
An Integration test [통합 테스트]
완전한 응용 프로그램을 통합적으로 테스트 하는 것을 말한다. 테스트 중인 모든 위젯과 서비스가 예상대로 함께 동작하는지 확인하는 것을 목표로 한다.
통합 테스트를 사용하여 앱의 성능 또한 확인 가능하며 일반적으로 서비스되는 플랫폼에 따라 앱의 경우 모바일 기기에서 웹의 경우 브라우저에서 테스트가 수행된다.
개발 분야마다 해당 테스트에 대해 부르는 명칭은 조금씩 차이가 있지만 일반적인 범주는 위의 세가지로 분류를 따른다.
각각의 테스트 마다 소모되는 비용과 기대할 수 있는 효과들이 차이점이 있는데 이를 도표로 살펴보면 아래와 같다.
일반적으로 비용과 신뢰도는 비례되는 성격을 가지는 것을 볼 수 있다.
이상이 TDD에 대한 이야기였으며 해당 글만을 가지고는 실무에서 구체적으로 어떻게 코드를 작성해야 되는지를 모두 파악하기엔 힘들 것이라고 생각한다.
여기에 대해선 해당 글에서 다루기엔 너무 방대한 내용이라 추후 Flutter를 중심으로 TDD에 대한 방법에 대해 보다 자세히 살펴보도록 하려고 한다.
TDD의 대해 많은 설명과 방법들이 있지만 본인이 왜 이것을 해야 되는지에 대한 납득이 없다면 그저 분위기에 휩쓸려 유행을 따라 가는 하나의 풍조에 지나지 않는다고 생각한다.
해당 글이 그 이유를 만드는데 있어서 조금이나마 도움이 되기를 바라며 보다 이를 자세히 알고 싶으신 분들은 아래 글들을 참고 하시면 좋을 듯 하다.