요구사항 분석이라는 부분은 어느정도 경력이 쌓이지 않으면 하기 어려워, 간략하게 하는 경우가 많다.
TDD는 요구사항 분석을 세세하게 하지 않아도 가능함
테스트 주도 개발 방법론
1. 테스트 주도 개발(TDD) 개요
1.1 테스트 주도 개발이란?
- 테스트 주도 개발(Test-Driven Development, TDD)
- 코드를 작성하기 전에 테스트 케이스를 먼저 작성하는 방식을 따르는 소프트웨어 개발 방법론 중 하나
- 개발 과정을 짧은 반복 주기로 나누고
- 각 주기마다 사용자의 요구 사항을 테스트 케이스로 변환하여
- 코드를 개선해 나가는 방식
- 전기전자학회(Institute of Electrical and Electronics Engineers, IEEE)에서 발행된 연구 논문에서 "TDD (Test-Driven Development)는 익스트림 프로그래밍 (XP) 개발 프로세스의 기본 관행 중 하나"라고 정리함
- TDD를 개발한 켄트 백(애자일 방법론의 개발자)은 2003년에 “TDD는 단순한 설계를 촉진시켜주며 자신감을 불어 넣어준다” 라고 말한 바가 있음
- 애자일 방법론 중 하나인 eXtream Programming(XP)의 'Test-First' 개념에 기반을 둔 단순한 설계를 중요시 함
- 애자일 방법론
- 신속한 반복 작업을 통해 실제 작동 가능한 소프트웨어를 개발하여 지속적으로 제공하기 위한 소프트웨어 개발 방식
- 작동하는 소프트웨어의 작은 구성 요소를 신속하게 제공하여 고객의 만족도를 개선하는 것이 핵심
- 적응형 접근 방식과 팀워크를 활용한 지속적인 개발에 중점
- 소프트웨어 개발에 필요한 작업을 알려주는 일련의 규정이 아니라, 협업과 워크플로우를 바라보는 하나의 관점이며, 우리가 무엇을 어떻게 만들지에 관한 선택을 안내하는 가치 체계를 가리킴
- 국내 기준으로는 많이 따르지 않고 있는 추세이다(거희 대부분이 제대로 못쓰는 경우가 많다)
- eXtream Programming(XP)
- 미래에 대한 예측을 최대한 하지 않고, 지속적으로 프로토타입을 완성하는 애자일 방법론 중 하나
- 이 방법론은 추가 요구사항이 생기더라도, 실시간으로 반영할 수 있음
- 애자일 방법론
- 목적
- 코드의 품질을 높이고
- 유지보수를 용이하게 하며
- 개발자의 생산성을 높이는 데 도움을 줌
- 설계 오류를 초기에 발견, 수정할 수 있게 지원
- 개발 과정에서의 오류와 리스크를 줄이기 위해 고안됨
- TDD의 핵심
- 실패하는 테스트 케이스를 먼저 작성하고
- 테스트를 통과하기 위한 최소한의 코드만을 작성하는 것
1.2 TDD의 적용 단계(4단계)
1.2.1 실패하는 테스트 작성
- 구현할 기능에 대한 작은 단위의 테스트 케이스를 먼저 작성
- 요구사항을 충족시키지 못하는 테스트 케이스를 작성함
- 이 단계에서는 기능이 어떻게 동작해야 하는지 명확히 정의함 ⇒ 개발해야 할 기능의 명세서 역할 수행
1.2.2 테스트를 통과하는 코드 작성
- 테스트를 통과하기 위한 최소한의 코드를 작성
- 이 단계에서는 코드의 품질이 아니라 테스트를 통과하는 것에만 집중함
1.2.3 리팩토링
- 테스트를 통과한 코드를 개선
- 이 단계에서는 코드의 품질 향상에 집중함
- 코드의 가독성 향상
- 중복된 코드 제거
- 필요 시 설계 개선
- 유지보수성 개선
1.2.4 점진적 코드 개선
- 1~3단계를 반복하여 점진적 코드 개선 추구
1.3 TDD의 장단점
1.3.1 장점
- 빠른 피드백
- 코드가 작성되기 전에 테스트가 준비되므로, 코드 작성 후 바로 피드백을 받을 수 있음
- 개발 과정에서의 버그를 사전에 예방할 수 있음
- 개발 과정에서의 리스크를 줄일 수 있음
- 개발자의 생산성 향상에 기여
- 높은 코드 품질
- 테스트를 먼저 작성함으로써 코드의 품질을 높일 수 있음
- 유지보수 용이
- 테스트 케이스가 존재하므로, 코드 변경 시에도 기존 기능이 정상적으로 동작하는지 쉽게 확인할 수 있음
1.3.2 단점
- 초기투자 필요
- TDD를 적용하는 데에는 시간과 노력이 필요함
- 초기 학습 곡선이 가파를 수 있음
- 생산성의 저하
- 개발 속도가 느려진다고 생각하는 사람이 많기 때문에 TDD에 대해 반신반의함
- 처음부터 2개의 코드를 짜야함
- 중간중간 테스트를 하면서 고쳐나가야 함
- TDD 방식의 개발 시간은 일반적인 개발 방식에 비해 대략 10~30% 정도로 늘어남
- SI 프로젝트에서는 소프트웨어의 품질보다 납기일 준수가 훨씬 중요하다 생각하기 때문에 TDD 방식을 잘 사용하지 않음
- 개발 속도가 느려진다고 생각하는 사람이 많기 때문에 TDD에 대해 반신반의함
- 사전 경험(충분한 연습과 경험)이 중요함
- 모든 상황에 TDD를 적용하기 어려울 수도 있음
- 테스트 케이스 작성에 대한 경험이 부족한 개발자에게는 도전적인 작업일 수 있음
- 기존 개발방식의 변경이 요구됨
- 이제까지 자신이 개발하던 방식을 많이 바꿔야 함
- 몸에 체득한 것이 많을 수록 바꾸기가 어려움
- 오히려 개발을 별로 해보지 않은 사람들에겐 적용하기가 쉬움
- 구조에 얽매임
- TDD로 프로젝트를 진행하면서 어려운 예외가 생길 수 있는데 그것 때문에 고민하는 순간이 찾아옴
- 원칙을 깰 수는 없고 꼼수가 있기는 한데 그 꼼수를 위해서 구조를 바꾸자니 이건 아무래도 아닌 것 같고, 테스트는 말 그대로 테스트일 뿐 실제 코드가 더 중요한 상황인데도 불구하고 테스트 원칙 때문에 쉽게 넘어가지 못하는 경우 등
- 개발자는 TDD에 대한 지속적인 학습과 실습을 통해 이 방법론을 자신의 개발 과정에 효과적으로 통합해야 함
1.4 TDD의 효과
1.4.1 디버깅 시간의 단축
- 유닛 테스팅을 하는 이점
- 사용자의 데이터가 잘못 나온다면 DB의 문제인지, 비즈니스 레이어의 문제인지, UI의 문제인지 바로 알 수 없기때문에 실제 모든 레이어들을 전부 디버깅 해야함
- TDD의 경우 자동화 된 유닛테스팅을 전재하므로 특정 버그를 손 쉽게 찾아낼 수 있음
- 테스트를 수업시 했기 때문에 디버깅 시간이 많이 단축된다.
1.4.2 가장 빠른 피드백
- 개발 프로세스에서는 보통 '인수 테스트'를 수행함
- 인수 테스트: 이미 배치된 시스템을 대상으로 클라이언트가 의뢰한 소프트웨어가 사용자 관점에서 사용할 수 있는 수준인지 체크하는 과정
- 이미 90% 이상 완성된 코드를 가지고 테스트하기 때문에 문제를 발견할 수는 있지만 정확하게 원인이 무엇인지 진단하기는 어려움
- TDD를 사용하면 기능 단위로 테스트를 진행하기 때문에 코드가 모두 완성되어 프로그래머의 손을 떠나기 전에 빠르게 피드백을 받는 것이 가능함
1.4.3 코드의 불안정성 개선 및 생산성 향상
- 코드가 내 손을 떠나 사용자에게 도달하기 전에 문제가 없는지 먼저 진단 받을 수 있으므로 코드가 지닌 불안정성과 불확실성을 지속적으로 해소해줌
- 켄트 백은 TDD는 불안함을 지루함으로 바꾸는 마법의 돌이라고 표현
1.4.4 프로그래머의 오버 엔지니어링 방지
- 프로그래머들은 간혹 계획하지 않았던 코드를 추가하여 오버 엔지니어링하는 경우가 있음
- TDD의 원칙: 테스트를 통과하기 위한 최소한의 코드만 작성 및 개선해야 함
- 기능 단위로 테스트를 진행하기 때문에, 문제가 발견되지 않은 코드에 영향을 줄 수 있는 오버 코딩은 하지 않을 수 있음
1.4.5 개발 이력의 활용
- TDD를 사용하면 개발 과정이 테스트 코드로 남기 때문에, 과거 의사결정을 쉽게 상기할 수 있다.
- TDD를 사용하면, 테스트 코드를 작성하는 과정에서 히스토리가 남음 ⇒ 어떻게 보면 과거의 나 자신과 프로그래머가 협업하는 것을 용이하게 만들어준다고 할 수 있음
- TDD를 통해 작성한 테스트 코드를 트래킹하면서 과거에 어떤 인과관계로 의사결정을 했는지 확인하기 쉬움
1.4.6 재설계 시간의 단축
- 테스트 코드를 먼저 작성하기 때문에 개발자가 지금 무엇을 해야하는지 분명히 정의하고 개발을 시작하게 됨
- 또한 테스트 시나리오를 작성하면서 다양한 예외사항에 대해 생각해볼 수 있음
- 이는 개발 진행 중 소프트웨어의 전반적인 설계가 변경되는 일을 방지할 수 있음
1.4.7 추가 구현이 용이함
- 개발이 완료된 소프트웨어에 어떤 기능을 추가할 때 가장 우려되는 점은 해당 기능이 기존 코드에 어떤 영향을 미칠지 알지 못한다는 것임
- TDD의 경우 자동화된 유닛 테스팅을 전제하므로 테스트 기간을 획기적으로 단축시킬 수 있음
1.5 TDD에 대한 편견과 실상
1.5.1 TDD는 무조건 해야 한다?
그렇지 않다.
- TDD가 프로그래머에게 주는 이점에 대해 나열하면, TDD가 모두에게 필요한 것처럼 느껴질 수 있음
- 그러나 프로그래머가 코드를 작성해 기능 하나를 추가할 때마다, 시간이 늘어난다고 본다면 TDD는 오히려 비효율적인 것처럼 보이기도 함
- TDD를 사용했을 때의 초기 비용이 TDD를 사용하지 않았을 때보다 크기 때문
- 일단 운영 코드를 테스트하기 위한 코드를 프로그래머가 따로 작성해야 한다는 점만 보아도 알 수 있음
- 프로그래머는 하나의 프로젝트를 완성하는데 걸리는 예상 일정과 자원을 고려해야 함
- 이에 따라 TDD를 사용할 수도, 사용하지 않기로 결정할 수도 있음
- 이에 따라 TDD를 사용할 수도, 사용하지 않기로 결정할 수도 있음
- TDD 사용 시, 일정 시점을 지나면 TDD를 사용하지 않을 때와 비교하여 시간 대비 비용이 더 커지지 않고 일정하게 유지됨
- 즉, TDD를 사용하기 시작하면 초기 비용은 더 많이 들 수 있으나 전체적으로 봤을 때 비용이 점진적으로 늘어나지 않음
- 따라서, TDD를 위한 환경세팅이 이미 잘 되어 있는 업무 환경이라면 TDD를 사용하는 편이 장기적으로는 효과적이라 할 수 있음.
1.5.2 TDD는 버그를 박멸한다?
- 그렇지 않다.
- TDD는 버그를 없애주는 도구가 아님
- 오히려 TDD를 사용하면 더 많은 버그를 사전에 발견할 수 있음
- 프로그래머가 작성한 코드가 사용자에게 도달하기 전에, 혹은 전체 코드를 완성하기 전에, 기능 단위로 문제를 개선할 수 있게끔 빠른 피드백을 전달하는 것이 TDD의 목적임
- 그래서 버그를 보다 빠르고 효과적으로 개선할 수 있도록 프로그래머를 도와줄 수는 있음
1.5.3 TDD는 항상 느리다?
- 그렇지 않다.
- TDD를 업무에 사용할 때 업무 속도가 느려진다고 느끼는 이유
- TDD를 처음 도입하면 TDD를 사용하기 위해 필요한 초기 자원이 미진해서 속도가 나지 않는다고 생각할 수 있음
- 회사에서 여러 프로그래머가 협업해야 하는 경우, TDD를 사용하기 위한 업무 프로세스가 익숙하지 않아 개발 속도가 느려진다고 느끼기도 함
- 테스트 코드 작성에 대한 업무 부담감
- 테스트 자동화를 위해 필요한 코드까지 프로그래머가 작성하고 관리해야 하므로 업무가 오히려 더 늘어나 비효율적이라 여길 수 있음
- 테스트 자동화를 위해 필요한 코드까지 프로그래머가 작성하고 관리해야 하므로 업무가 오히려 더 늘어나 비효율적이라 여길 수 있음
- TDD를 처음 도입하면 TDD를 사용하기 위해 필요한 초기 자원이 미진해서 속도가 나지 않는다고 생각할 수 있음
- TDD 자체가 목적이 되어서는 안됨
- TDD는 공동의 목표를 효율적으로 달성하기 위한 도구임
1.6 TDD에 대한 프로그래머들의 의견
- TDD에 대한 프로그래머들의 의견은 언제나 엇갈림
- TDD의 실효성을 업무로 경험한 사람들은 TDD를 더 효과적으로 실무에 적용하기 위해 고민함
- 반면, 회사마다 일하는 방식이나 처한 업무 환경에 편차가 있다보니 일각에서는 실무에서 TDD를 사용하는 건 사실상 현실과 괴리감이 크다는 의견도 있음
1.7 일반 개발 방식 vs. TDD 개발 방식
1.7.1 일반 개발 방식
- 개발 주기
- 요구사항 분석 → 설계 → 개발 → 테스트 → 배포
- 소프트웨어의 개발을 느리게 하는 잠재적인 위험 존재
- 소비자의 요구사항이 처음부터 명확하지 않을 수 있음 → 처음부터 완벽한 설계는 어려움
- 자체 버그 검출 능력 저하 또는 소스코드의 품질 저하 위험 존재
- 자체 테스트 비용 증가 가능성
- 완전하지 않은 초기 설계에 대한 대응
- 고객의 요구사항 또는 디자인의 오류 등 많은 외부 또는 내부 조건에 의해, 재설계하여 점진적으로 완벽한 설계로 진행
- 재설계로 인해 개발자는 코드를 삽입, 수정, 삭제 하는 과정에서 불필요한 코드가 남거나 중복처리 될 가능성이 큼
- 이러한 코드들은 재사용이 어렵고 관리가 어려워져 유지보수를 어렵게 만듦
- 작은 부분의 기능 수정에도 모든 부분을 테스트해야 하므로 전체적인 버그를 검출하기 어려워짐
- 자체 버그 검출 능력 저하
- 결과적으로 어디서 버그가 발생할지 모르기 때문에 잘못된 코드도 고치지 않으려 하는 현상이 나타남
- 이 현상은 소스코드의 품질 저하과 직결됨
- 작은 수정에도 모든 기능을 다시 테스트해야 하는 문제로 인해 자체 테스트 비용 증가
1.7.2 TDD 개발 방식
- 개발 주기(개발 주기부터 다름)
- 디자인(설계) → 테스트 코드 작성 → 코드 개발 → 리팩토링 → 반복
- 요구사항 분석이 없지는 않지만 많이 줄어들음
- 단계별 작업 및 주의사항
- 디자인(설계) 단계
- 프로그래밍의 목적을 반드시 미리 정의해야 함
- 무엇을 테스트해야 할지 미리 정의(테스트 케이스 작성)해야 함
- 테스트 코드 작성 단계
- 작성 도중에 발생하는 예외 사항(버그, 수정사항)들은 테스트 케이스에 추가하고 설계를 개선함
- 테스트 케이스의 작성으로 인해 자연스럽게 설계가 개선됨 → 재설계 시간 절감
- 코드 개발 단계
- 테스트를 통과한 코드만을 코드 개발 단계에서 실제 코드로 작성함
- 리팩토링 단계
- 좋지 않은 코드를 정리 및 개선
- 각 단계 반복
- 이러한 단계가 반복되면서 자연스럽게 코드의 버그가 줄어들고 소스코드는 간결해짐
- 디자인(설계) 단계
- Bad Smell
- 코드에서 발견되는 잠재적인 문제를 나타내는 용어
- 코드의 품질이 떨어지거나 유지보수가 어려워질 수 있는 징후를 의미
- 버그는 아니지만, 코드의 설계나 구현이 좋지 않다는 신호로 받아들여짐
- Bad Smell의 예
- 중복 코드: 동일한 코드 구조가 여러 곳에 반복되는 경우
- 긴 메서드: 너무 길고 많은 일을 하는 메서드
- 큰 클래스: 너무 많은 책임을 가진 클래스
- 기능 질투: 다른 클래스에 더 관심이 많은 메서드
- 데이터 덩어리: 함께 전달되는 경향이 있는 데이터 그룹
- Bad Smell을 해결하기 위해서는 리팩토링이 필요함
- 리팩토링: 코드의 외부 동작을 변경하지 않으면서 내부 구조를 개선하여 가독성을 높이고 복잡성을 줄이며 유지보수를 쉽게 만드는 과정
1.7.3 TDD의 메인 프로세스
- 3가지 단계
- RED : 테스트 실패
- GREEN : 테스트 성공
- REFACTOR : 리팩토링
- RED: 테스트 실패
- 구체적인 하나의 요구사항을 검증하는 하나의 테스트를 추가
- 추가된 테스트가 실패하는지 확인
- 실패하는 것이 확인 되어야 테스트가 검증력을 가진다고 신뢰할 수 있음
- 실패의 이유는 운영 코드가 아직 변경되지 않았기 때문이어야 함
- 테스트 코드의 문제이면 안됨
- GREEN: 테스트 성공
- 추가된 테스트를 포함하여, 모든 테스트가 성공하게끔 운영 코드를 변경
- 테스트의 성공은 모든 요구사항을 만족했음을 의미함
- 테스트 성공을 위한 최소한의 코드 변경만 진행
- TDD에서는 테스트 성공을 위한 최소한의 코드 그 이상을 변경하거나 추가하면 안됨
- 테스트 되지 않은 코드가 중간에 추가되면, 이후 리팩토링 등의 다른 프로세스에서 어떤 부작용을 가져올지 알 수 없기 때문
- REFACTOR: 리팩토링
- 코드베이스 정리
- 인터페이스 뒤에 숨어 있는 구현 설계를 개선
- 가독성, 적용성, 성능을 고려
- 테스트 주도 개발 세부 흐름
- 단위 테스트 작성 → 단위 테스트 실행 → 운영 코드 작성 → 단위 테스트 실행 → 설계 개선(리팩토링) → 단위 테스트 → … 실행 반복
- TDD의 대표적인 도구: JUnit
- 전 세계적으로 가장 널리 사용되는 'Java 단위 테스트 프레임워크'
- JUnit을 기반으로 다양한 파생 프레임워크(xUnit) 개발
- CUnit (C)
- CppUnit (C++)
- PyUnit (Python) 등
1.8.1 수동 테스트
- 품질 담당자(QA)가 UI를 사용해서 기능 검증
- 사람이 검증하기 때문에, 사용자와 가장 가까운 관점에서 테스트가 가능
- 소프트웨어의 모든 코드가 현장에 배치된 후에 테스트 가능
- 어떤 기능이 정상 작동하기 위해 필요한 모든 코드가 준비되어야 함
- 가장 온전한 전체 코드를 검증하는 테스트 방식
- 단점
- 실행 비용이 높고, 결과의 변동이 큼
- 전문성을 지닌 담당자가 비용을 줄이기 위해 노력하지만, 휴먼 에러의 가능성을 완전히 없애기는 어려움
- 시간이 흐르면서 추가되는 기능은 자연스럽게 증가
- 문제는 어떤 기능을 추가하거나 개선하기 위해 작성한 코드는 다른 코드에 영향을 미친다는 점
- 테스트를 진행하더라도, 새로 추가된 코드로 인해 영향을 받을 기존 코드에 대한 테스트는 건너뛰거나 충실히 진행하지 못하는 경우가 많음
- 실행 비용이 높고, 결과의 변동이 큼
1.8.2 테스트 자동화
- 수동 테스트가 지닌 한계를 보완하기 위해 등장한 도구
- 사람이 직접 테스트하지 않고, 어떤 기능을 검증하는 또 다른 코드를 작성하는 방식
- 단점
- 수동 테스트에 비해 프로그래머가 더 많은 코드를 작성해야 함
- 운영 코드를 테스트하기 위한 별도의 코드를 추가 작성해야 하기 때문
- 테스트 코드의 작성과 관리가 프로그래머 개인의 역량에 달려 있음
- 업무 자체가 허들이 될 수도 있음
- 업무 자체가 허들이 될 수도 있음
- 수동 테스트에 비해 프로그래머가 더 많은 코드를 작성해야 함
- 장점
- 테스트에 드는 비용이 매우 낮아짐
- 휴먼 에러의 가능성도 줄어들기 때문에, 수동 테스트에 비해 테스트 자체에 대한 신뢰도는 매우 높아짐
1.8.3 인수 테스트
- 배치된 시스템을 대상으로 검증하는 방식
- 주로 클라이언트가 의뢰한 소프트웨어를 최종적으로 사용할 수 있는 수준인지 점검하는 테스트
- 전체 시스템의 이상 여부가 없는지 확인하며, 사용자 관점으로 체크하기 때문에 신뢰도가 높은 테스트 방법
- 단점
- 비용이 매우 높음
- 코드 작성부터 관리, 테스트 실행까지 자원이 많이 소요됨
- 프로그래머 입장에서 받을 수 있는 피드백의 질이 떨어짐
- 문제는 파악할 수 있으나, 그 원인까지 단번에 알려주지는 못하기 때문
- 비용이 매우 높음
1.8.4 단위 테스트
- 인수 테스트의 단점을 보완하는 검증 방식
- 시스템의 일부(하위 시스템)를 대상으로 기능을 검증하는 테스트
- 전체 시스템을 배치해놓고 진행하지 않으므로, 비용이 상대적으로 낮은 편
- 인수 테스트와 비교해서, 단위 안에서 버그가 있다는 걸 상대적으로 자세히 알 수 있음
- 프로그래머 입장에서는 문제 해결을 위해 필요한 피드백을 적절하게 받을 수 있음
- 전체 시스템의 이상 여부를 판단하는 신뢰도는 낮아짐
- 단위 테스트에서 문제가 없다고 판단되어도, 전체 시스템이 유기적으로 연결될 때 오류가 날 수도 있기 때문
1.9 테스트 주도 개발의 이점에 대한 통계와 연구
- TDD는 기존 테스트 개발보다 느리다, 빠르다?
- TDD가 프로그래밍 프로세스를 빠르게 해준다는 여부와 관련하여 다양한 소스로부터 상반된 통계 자료들이 나온다.
- Microsoft와 IBM팀 소프트웨어 엔지니어들의 사례 연구는 TDD 기술을 사용했을 때 “팀들은 초기 개발 시간이 15-35% 정도 늘어났다” 라고 결론지었다. 하지만 이 숫자들은 “경영진에서 주관적으로 추정한” 수치라고 언급한다.
- 품질이 개선되었다는 Microsoft와 IBM의 연구의 관점에서 보았을 때, 만약 장기적으로 본다면 TDD는 나중에 결함들을 고쳐야하는 시간을 절약해줄 수 있다고 볼 수 있다. Microsoft와 IBM 팀들도 이 주장에 동의했다.
- TDD를 사용할 때 경험많은 전문가들의 초기 인식에 대한 연구는 “어디서부터 시작할지 이해하고 기능을 위해 아직 존재하지도 않은 테스트를 만드는 방법에 능숙해지는 초기 어려움을 극복해내면, 참가자들은 새로운 기능들을 구현하고 광범위한 테스트 범위로 인하여 수정하게 될 때 더 큰 자신감을 얻게 되었다” 라고 결론을 짓는다. 이는 시간이 지남에 따라 상황이 개선된다는 걸 말해준다.
- 온라인 출판 플랫폼인 Medium.com에서 글을 쓰는 프로그래머이자 책 “Composing Software”와 “Programming JavaScript Applications”의 저자인 Erick Elliot은 TDD가 그의 삶을 어떻게 변화시켰는지에 중점을 둔다. Elliot은 이 프로세스가 처음에 얼마나 느려질 수 있는지에 대해 지적하지만 “2년정도 지난 어느 시점에서 마법 같은 일이 일어나기 시작했다. TDD를 안썼을 때보다 단위 테스트를 통해 코딩을 훨씬 더 빠르게 하기 시작했다.” 라고 말했다.
- TDD는 처음 초기 단계에서 느려 보인다. 하지만 장기적으로 보았을 때 더 높은 품질의 코드로 절약된 시간이 초기 단계에서 쓴 시간을 상쇄시켜줄 수 있다. 또한 프로그래머들이 TDD에 능숙해지는만큼 더 빨리 작업할 수 있게 해준다고 볼 수 있다.
- 높은 품질의 결과물을 만들기 위해서 시간이 얼마나 걸리는 지 측정하려면 많은 요인들을 고려해봐야한다.
- TDD가 버그를 줄여주는가?
- 위에서 TDD의 주요 장점 중 하나는 버그가 적다는 것인데 과연 통계 자료는 어떨까?
- 위에서 언급된 Microsoft와 IBM 엔지니어링 팀의 연구는 “TDD 방식을 사용하지 않은 유사한 프로젝트에 비해 4개 결과물의 시험판 결함 밀도가 40% 에서 90%까지 감소했다.” 라고 발표했다. 특히 IBM 팀은 결함 밀도가 40%, Microsoft는 60-90% 감소되었다고 한다.
- TDD의 높은 품질에 대한 통계 자료는 어떠한가?
- 핀란드에서 열린 IEEE(전기전자학회)의 2007년 첫 번째 국제 심포지엄에서 발표된 연구 결과를 기반으로 Maria Siniaalto와 Pekka Abrahamsson은 TDD로 개발되지 않은 소프트웨어와 비교할 때 TDD가 더 나은 코드 품질을 생성한다는 것을 발표했다.
- 그들의 논문에서는 TDD가 프로세스 트래킹과 작업 판단을 향상시켰다는 중국에서 진행된 연구를 인용한다. 동일한 연구에서는 “TDD는 또한 다음과 같은 일관된 관행과 가이드라인을 개선한다”라고 정리한다. 결과적으로 더 적은 오류와 품질이 높아진다. 또한 TDD를 사용한 팀은 오류를 더욱 더 빠르게 수정할 수 있었다.
- 평균 약 10년 전문 경험이 있는 개발자들이 TDD를 활용했을 때 그들의 인식을 조사하기 위한 연구에서는 “TDD는 코드를 더 읽기 쉽고 개선하는데 도움을 주었다” 라고 말한 개발자를 예로 든다. 또다른 참가자는 “TDD는 더 나은 유지보수를 가능케해준다”라고 말했다.
- TDD는 단순한 설계를 도와주는가?
- North Carolina State University 컴퓨터학부의 Boby George와 Laurie Williams는 24명의 프로그래머를 두 그룹으로 나누는 실험을 했다. 한 그룹은 TDD를 사용하고 또 다른 그룹은 선형적인 방식을 사용하게 한 것이다.
- 그들은 참가자들 중 “92%는 TDD가 높은 품질의 코드를 생산해낸다고 여겼고, 79%는 TDD가 단순한 설계를 이끈다고 생각했으며, 71%는 이 방법이 특출나게 효과적이었다라는 의견을 냈다”라고 발표하였다.
- 품질에 관한 이 TDD 통계 자료는 TDD가 실제로 높은 품질의 코드와 단순한 설계를 이끈다는 강력한 근거이다.
- 한 연구에서는 참가자들의 79%가 TDD가 단순한 설계로 이끌었다 라고 말했다.
- 무료 학습 포털 사이트 Guru99.com에서 게시된 한 글에서 Kanchan Kulkarni는 “TDD는 코드를 더 간단하고 명확하게 해준다. 또 개발자들이 적은 문서량을 유지하게 해준다.” 라고 얘기했다.
- TDD 설계를 따르는 것은 쉬운까?
- George와 William의 실험에 따르면 전문 개발자들의 56%는 TDD의 사고방식은 적응하기 어렵다고 믿었고 23%는 초기 설계 단계가 없기 때문에 이러한 어려움이 생긴다고 주장했다. 전체 답변 중 40%는 TDD에 적응하기 어렵다라고 대답했다.
- 이러한 TDD 적응에 관한 통계는 TDD가 적용되기엔 어렵다고 보인다.
TDD는 과대평가 되었는가? - 머신 러닝, AI, 인프라, DevOps 및 애자일에 관심이 있는 자칭 풀스택 소프트웨어 개발자인 Tylor Borgeson은 Medium.com에 게시된 글의 제목을 <“TDD는 과대평가 되어있다(Test-Driven Development is Overrated)”>라고 짓는다. 하지만 이 제목에 인용부호를 사용하여 썼다는 것은 사실 그가 말하려는 건 상반된 내용이라는 걸 암시한다.
- Borgeson은 이 방식이 과대평가 되어있고 느리다고 말하는 사람들은 대부분 이 방법을 장기간 동안 사용해보지 않았다고 지적한다. 그리고 그는 “그럼 이제 TDD로 고통을 안 받을 때까지 가서 연습해보아라” 라고 하며 글을 마쳤다.
## TDD 요약
### 테스트 주도 개발(TDD)이란?
- 코드를 작성하기 전에 테스트 케이스를 먼저 작성하는 방식.(개발 과정을 짧은 반복 주기로 나누고, 각 주기마다 사용자의 요구 사항을 테스트 케이스로 변환하여 코드를 개선해 나가는 방식)
- 애자일 방법론 중 하나인 **eXtream Programming(XP)**의 'Test-First' 개념에 기반.
- 짧은 반복 주기를 통해 코드 품질을 높이고 유지보수를 쉽게 만들어 줌.
### 목적
- 코드의 품질을 높임
- 유지보수를 용이하게 함
- 개발자의 생산성을 높이는데 도움을 줌
- 설계 오류를 초기에 발견, 수정할 수 있게 지원
- 개발 과정에서의 오류와 리스크를 줄이기 위해 고안됨
### TDD의 핵심 단계
- 실패하는 테스트 작성: 요구사항을 테스트로 정의.
- 테스트를 통과하는 코드 작성: 최소한의 코드를 작성하여 테스트 통과.
- 리팩토링: 코드 품질을 개선하고 중복된 코드 제거.
- 점진적 코드 개선: 위 단계를 반복하여 기능을 확장하고 개선.
### 장점
- 빠른 피드백을 제공하여 버그를 조기 발견.
- 유지보수가 용이하고, 코드 품질이 높아짐.
- 개발 이력을 기록하여 과거의 의사결정을 상기 가능.
### 단점
- 초기 학습이 필요하고, 생산성 저하에 대한 우려.
- 초기 투자 비용과 시간이 더 들 수 있음.
- SI 프로젝트 등에서는 납기일 준수가 중요하여 잘 사용되지 않음.
#### TDD의 효과
- 디버깅 시간 단축: 코드에 문제가 발생할 때, 어느 부분에서 발생했는지 쉽게 파악 가능.
- 빠른 피드백: 기능 단위로 테스트를 진행하므로 빠르게 피드백 제공.
- 재설계 시간 단축: 개발 과정에서의 불필요한 설계 변경을 줄여줌.
- 오버 엔지니어링 방지: 테스트를 통과하는 최소한의 코드만 작성.
## 일반 개발 방식 vs TDD 개발 방식
### 일반 개발 방식 :
##### 개발 주기
- 요구사항 분석 → 설계 → 개발 → 테스트 → 배포
- 개발 초기 단계에서 모든 요구사항을 분석하고 설계를 완료한 후, 코드를 개발, 이후 전체 시스템에 대해 테스트를 수행하고 배포
##### 요구사항 분석
- 요구사항 분석이 초기 단계에서 충분히 이루어지며, 개발 과정에서 큰 변화가 있을 경우 재설계가 필요할 수 있다.
- 요구사항이 명확하지 않으면 초기 설계가 불완전할 수 있고, 이후 수정이 어려워질 수 있다.
##### 코드 작성 및 테스트
- 전체 코드 작성 후, 모든 기능이 구현된 후에 통합 테스트를 수행
- 버그를 발견하면 수정하고, 다시 전체 테스트를 실행하여 검증
##### 리펙토링 및 유지보수
- 초기 설계와 개발이 완료된 후, 유지보수와 리팩토링이 필요할 때 진행
- 코드의 품질 저하가 발생할 수 있으며, 버그 수정 시 전체 시스템에 영향을 미칠 수 있다.
##### 버그 검출 및 수정
- 테스트는 개발 후에 진행되며, 버그는 나중에 발견될 수 있다.
- 버그 발견 시, 모든 기능을 다시 테스트해야 하므로 비용이 증가할 수 있다.
##### 개발 속도 및 비용
-초기 개발 속도가 빠를 수 있으나, 후속 수정과 테스트 비용이 많이 들 수 있다.
- 버그 수정 및 변경이 전체 시스템에 영향을 미칠 수 있다.
### TDD 개발 방식 :
##### 개발 주기
- 디자인(설계) → 테스트 코드 작성 → 코드 개발 → 리팩토링 → 반복
- 개발 과정에서 먼저 테스트 케이스를 작성하고, 이를 기반으로 코드를 개발, 테스트가 통과하면 리팩토링을 통해 코드를 개선하고, 이 과정을 반복
##### 요구사항 분석
- 요구사항을 테스트 케이스 형태로 정의하여, 개발 과정에서 점진적으로 요구사항을 충족시키는 방식
- 설계는 테스트 케이스와 함께 점진적으로 개선되며, 초기 요구사항이 불완전해도 테스트를 통해 기능을 검증하고 수정할 수 있다.
##### 코드 작성 및 테스트
- 테스트 케이스를 작성한 후, 이를 통과시키기 위한 최소한의 코드를 작성
- 각 기능이 개발될 때마다 테스트를 통해 검증하며, 테스트를 통과한 후 코드 리팩토링을 수행
##### 리펙토링 및 유지보수
- 코드 작성 후 바로 리팩토링을 수행하여 코드의 품질을 유지
- 테스트가 있어 코드 변경 시 기존 기능의 정상 동작을 확인할 수 있어 유지보수가 용이
##### 버그 검출 및 수정
- 테스트를 먼저 작성하므로, 버그를 조기에 발견할 수 있다.
- 기능 단위로 검증하며, 테스트 케이스가 자동화되어 있어 버그 수정이 효율적이다.
##### 개발 속도 및 비용
- 초기 비용과 학습 곡선이 있을 수 있지만, 장기적으로 유지보수와 코드 품질이 개선된다.
- 개발 초기 단계에서 더 많은 시간과 노력이 들 수 있지만, 전체적으로는 더 안정적이고 품질 높은 소프트웨어를 제공할 수 있다.
- 오늘의 회고 페이지로 이동
'PYTHON-BACK' 카테고리의 다른 글
#파이썬 24.09.20_Django 기반의 테스트 주도 개발 방법론(TDD)&API 문서화 (1) | 2024.09.20 |
---|---|
#파이썬 24.09.20_Django 기반의 테스트 주도 개발 방법론(TDD)&API 문서화 (0) | 2024.09.20 |
#파이썬 24.09.02(월) ~ 24.09.13(금) 마켓컬리 클론코딩 프로젝트 (2) | 2024.09.13 |
#파이썬 33일차_온라인 상점 구축 프로젝트3 (0) | 2024.08.27 |
#파이썬 32일차_온라인 상점 구축 프로젝트2 (0) | 2024.08.26 |