작성
·
703
·
수정됨
0
안녕하세요! 강의를 드는 중 의아한 부분이 있는데요.
제가 알고, 공부했던 TDD 와는 달라서 좀 의문이네요.
제가 아는 TDD는 Red - Green - Refactor 사이클을 통해 테스트 코드를 작성하면서 자연스럽게 프로덕트 코드가 생성되는 방법입니다. 그 과정은 매우 세밀하고, 정말 짧은 주기로 테스트를 돌려봐야하죠. 강의에서는 프로덕트 코드를 테스트 파일에 작성하는 것으로 밖에 안 보이고 POJO 상품등록하는 로직이 완성될 때까지 테스트를 단 한 번 돌려본다는 게 의아하네요.
테스트 파일에 아무런 테스트 없이 내부 클래스로 프로덕트 코드를 작성하고 다 만들어지면 그 클래스를 옮기는 게 TDD가 맞나요? 이 정도 TDD라면 프로덕트 코드 먼저 만들고 단위 테스트 작성하는 것과 별반 차이가 없다고 느껴져요.
제가 순수 자바로만 TDD를 공부했기 때문에 스프링 부트에서 어떻게 하는 지 모르는 걸 수도 있는데, TDD 근간이 달라지는 것 같아 정말 순수하게 궁금합니다.
답변 2
1
TDD는 실용적 TDD와 원칙적 TDD로 나뉘는데, 강사님이 하시는건 실용적 TDD의 일부라고 생각됩니다.
원칙적 TDD는 질문자님 말씀대로 테스트 코드를 작성하며 사이클을 통해 비즈니스를 완성해 가는 과정이라면, 실용적 TDD는 테스트 코드를 먼저 작성하던, 비즈니스 코드를 먼저 작성하던 결국에는 테스트 코드가 함께 해야한다는 것이며, 이를 통해 SW 아키텍처가 테스트 가능한 코드로 진화하는가, 비즈니스 검증을 견고히 하고 있는가를 확인하는 과정입니다.
실용적 TDD에 대한 내용을 어디서 볼 수 있나요?
실무에서는 생산성이 중요하죠. 그에 맞춰 변화한 것이 실용적 TDD 또는 실용주의 TDD 입니다.
현업에서 발생하는 이슈기 때문에 구글링해도 안나오는게 맞습니다. 딱히 논란거리도, 재밌는 토론거리도 안되기 때문이죠.
실용적 TDD는 테스트를 먼저 작성해야하는 TDD가 아니라, 그냥 테스트 코드 작성과 테스트 커버리지의 중요성에 대한 내용으로 생각됩니다.
아니요! 테스트 코드를 먼저 작성해도 됩니다 🙂
그리고 테스트 커버리지는 중요하지 않습니다. 커버리지가 중요하다고 생각해 불필요한 테스트 코드까지 찍어내는 일은 절대로 절대로 있어선 안됩니다.
중요한 것은 테스트 코드를 잘게 잘게 쪼개어 내어도, 그 코드를 통해 정확히 기능의 동작을 확인할 수 있는가입니다. 즉, 유의미한 테스트 코드만 작성해라! 가 중요 포인트겠네요.
TDD가 아닌데 왜 실용적 "TDD"가 되나요?
우선 'TDD를 어떻게 하는가?' 라는 것은 중요하지 않다고 생각합니다. 테스트에 관심 있는 개발자들은 'TDD를 하는 목적이 무엇인가?'란 질문에 본인만의 답을 찾아야 한다고 생각해요.
제 답은 테스트 코드를 작성하는 목적 자체가 TDD를 하는 목적과 같다입니다. (하지만 TDD라고 하는 단어 자체는 중요하지 않습니다. )
우선 테스트 코드를 제대로 작성하지 않으면 어떻게 될까요?
단순히 "기능이 돌아가기만 하면 됐지!", "커버리지 높게 쳐주면 되는거 아니야?", "요구사항 만족했잖아?" 라는 마인드로 비즈니스 코드와 테스트 코드를 작성하면 그 서비스는 빠른 시일 내에 장애가 터질거고, 장애를 찾기 위해 버그 잡느라 시간을 많이 소비해서 고객 이탈이 발생할 겁니다.
또한 요구사항이 변경해 코드도 변경해야 하는 상황이 왔을 때라면, 위 3가지 마인드로 작성한 코드는 그냥 새로 개발하는게 더 빠를지도 모릅니다. 왜냐면 분명히 구조적으로 결함이 있을 수 밖에 없을 거거든요. (물론 새로 개발하는 것도 구조가 받쳐줘야 가능한 상황이 분명 있습니다.)
그럼 테스트 코드를 잘 작성하면 어떻게 될까요?
코드 구조가 테스트 가능성을 갖게 됩니다. 이 말은 프레임워크나 인프라 같은 예측 불가능한 요소들을 예측 가능하게 바꿔서 개발자가 원하는 결과를 쉽게 만든다는 것입니다. 그렇게 하면 테스트 코드가 실패한 다고 해서 불안해지지 않죠. 내가 만든 코드에서 버그를 찾으면 그만이거든요. 디버깅 자체가 쉬워집니다.
또한 제가 위에서 테스트 코드를 잘게 쪼개어 내어도, 기능이 정확히 동작함을 확인할 수 있어야 한다고 했습니다? A라는 기능을 A, B, C, E라는 기능으로 나눈 다음에 합쳐서 A라는 기능이 완성되도록 리팩토링 한 다음에 A 기능 전체를 테스트 하던, A, B, C, E 기능을 나누어 테스트 하던 결과가 동일해야 한다는 겁니다. 코드는 응집도를 높이고 결합도를 낮추게 되는거죠.
이 외에도 여러 장점들을 갖게 되죠. 여러 설계 방식을 지원하기 좋은 구조를 갖는다 던가, 테스트 코드 자체가 문서가 된다던가, 테스트 코드를 통해 빠른 피드백을 받게 된다던가, 유지보수성이 좋아진다던가 등등..
그런데 TDD를 공부하다 보면 이런 장점들이 제가 말한 테스트 코드를 작성해서 얻는 이점과 동일 하다는 게 보이지 않나요? ㅎㅎ. 결국에 테스트 코드를 작성하는 목적이 TDD의 목적과 일치해지면 결국 남는건 테스트 코드뿐이라는 겁니다.
아무튼 결론은 TDD <-- 단어와 행위 자체보단 목적에 무게중심을 두고 공부하자! 입니다.
아래 키워드를 몇 가지 드릴테니 공부해 보시고 본인만의 답을 찾을 수 있으면 좋겠습니다.
[클린 아키텍처, DDD, 객체지향 사실과 오해, 테스트 피라미드, Ci/CD]
1
안녕하세요, 인프런 AI 인턴입니다.
님께서 말씀하신 Red - Green - Refactor 사이클은 TDD(Test-Driven Development)의 핵심 원리이며, 이 원리에 따라 테스트 코드를 먼저 작성하고 그 테스트를 통과하기 위한 프로덕트 코드를 작성하는 과정을 반복함으로써 개발을 진행합니다. 이는 곧 테스트 코드 없이 프로덕트 코드를 먼저 작성하는 것과 다릅니다.
스프링 부트 환경에서 TDD를 적용할 때도 본질적인 사이클은 동일합니다. 다만, 스프링 부트와 같은 프레임워크를 사용할 경우, 프레임워크가 제공하는 여러 테스트 유틸리티와 지원 클래스들을 활용해 좀 더 효율적으로 TDD를 수행할 수 있습니다. 예를 들어, 스프링 부트는 테스트를 위한 다양한 유틸리티와 지원 클래스를 제공하며, spring-boot-starter-test
스타터를 통해 일반적인 테스트 의존성을 제공합니다.
또한, 스프링 애플리케이션 테스팅에 대해 Spring Framework의 전용 테스트 모듈을 사용할 수 있으며, 단위 테스트와 통합 테스트를 위한 다양한 지원을 받을 수 있습니다. 단위 테스트는 실제 의존성 대신 모의 객체를 사용할 수 있으며, 통합 테스트는 애플리케이션의 배포나 다른 인프라에 연결하지 않고도 실시할 수 있습니다.
테스트 코드 내에 프로덕트 코드를 작성한 뒤 이를 옮기는 방식은 TDD의 전형적인 접근 방식과는 다소 차이가 있습니다. TDD는 테스트를 먼저 작성하고 테스트에 실패한 후에만 프로덕트 코드를 작성하는 접근법을 따릅니다. 따라서, TDD의 핵심 원칙과 맞지 않는 부분이 있다면, 해당 접근 방식에 대해 깊이 고민해보고, 필요하다면 다른 방법을 탐색하는 것이 좋습니다.
스프링 부트에서의 TDD 적용 방법이나 스프링 프레임워크의 테스트 지원에 대해 궁금하시다면, Spring Boot Reference Documentation 및 Spring Framework 테스트 문서를 참고하시는 것을 추천드립니다.
친절한 답변 감사합니다!
그런데 TDD와 테스트 코드 작성 그 자체는 엄연히 다르다고 알고 있습니다.
그런데 답글의 내용 중
이 부분을 보면 말씀하신 실용적 TDD는 테스트를 먼저 작성해야하는 TDD가 아니라, 그냥 테스트 코드 작성과 테스트 커버리지의 중요성에 대한 내용으로 생각됩니다. TDD가 아닌데 왜 실용적 "TDD"가 될까요?
혹시 원칙적 TDD와 실용적 TDD에 대한 내용을 어디서 볼 수 있을까요? 구글에 검색해도 뭐가 안 나오네용..