패스트캠퍼스 이규원의 현실 세상의 TDD 강의 후기와 이후 TDD에 대한 생각
목차 펼치기
머리말
머리말
테스트 코드 작성과 TDD에 대해서 콘퍼런스 세션을 듣거나 다른 사람의 글을 읽은 적은 있지만, TDD는 커녕 테스트 코드 작성 경험도 없다시피했다. 많은 상태와 UI를 다루고, 빠르게 기획이 변경되는 프런트엔드에서 쉽지 않을 것이라 생각하기도 했다. 그런데 이번에 새로 합류한 팀은 UseCase 단위로 테스트 코드를 작성하여 도메인 논리를 검증하는 것을 적극 사용하고 있어 빠르게 관련된 지식을 탑재하는 게 필요했다. 개발 리드분으로부터 패스트캠퍼스의 ‘이규원의 현실 세상의 TDD’ 강의를 추천받았고, 이 글은 그 강의를 듣고 작성하는 후기이다.
후기
후기
강의에 대해
강의에 대해
강의는 총 두 편이 있는데, 첫 강의명이 이론편이라고 되어있지는 않지만 편의상 이론편과 실전 편이라고 지칭하겠다. 이론편은 약 11시간, 실전편은 약 13시간 정도의 러닝타임으로 구성되어 있다. 나에게는 생각보다 말의 속도가 느리게 느껴져서 1.2배속으로 시청했고, 별 부담없이 들을 수 있었다. 중간중간 코딩 시간이나 비슷한 작업을 할 때에는 조금씩 앞으로 넘기면서 시청하여 러닝타임보다는 적게 시간을 사용했다.
이론편에서는 테스트 기법과 TDD에 대한 설명, 테스트 더블과 Mockists와 Classicists, 테스트를 기반으로 한 개발 방식에 대한 내용 등을 다루고 있다. 실전편에서는 주문 및 정산 기능 개선과 B2B 계정관리 기능 개선이라는 작업을 통해 TDD를 어떻게 적용하는지 직접 개발하며 생각의 흐름을 알려주는 방식으로 진행되었다.
이론과 개념에 대한 정의부터 부족했던 나에게 이론편은 많은 도움이 되었다. 강의를 듣고 난 후 이전에 작성한 테스트 코드를 리팩터링했는데, 처음보다 한결 그림이 그려지는 느낌이었다. 실전편은 실제 코드를 개선하는 과정에서 생각의 흐름을 들을 수 있는 것은 좋았으나, 강의의 절반 정도는 남겨두었다. 이후에는 강의가 아닌 실제 테스트 코드를 작성하는 과정에서 훈련하고, 다른 테스트 관련 책을 읽는 방식으로 더 학습할 예정이다. TDD에 대한 길을 찾고 있는 단계라면, 꽤 도움이 많이 될 수 있는 강의라고 생각한다.
TDD에 대한 생각
TDD에 대한 생각
강의 내용에도 나오는 것처럼 인간 친화적 소통 수단인 UI 단계에서는 테스트 자동화 비용이 높기 때문에 효과적이라고 생각되지는 않는다. 하지만 내부 논리일수록 그것이 특히 복잡한 도메인 논리일수록 테스트 자동화는 소프트웨어 회귀를 방지하거나 개발자가 안심하고 작업할 수 있는 환경을 만들어 줄 수 있다는 것에는 공감한다.
TDD에 대해 멘탈 모델이 바뀌기도 했다. 개발 과정에서 결과물을 보고 다시 코드를 수정하거나, 버그를 재현하며 원인을 분석하고 수정해가는 과정과 본질적으로 다르지 않게 느껴진다. 테스트 코드는 초기 구축 비용만 들이면 자동화를 통해 이 과정에서 들어가는 인력을 대체하여 안정적으로 프로그래머에게 피드백을 전달해준다.
테스트 코드를 먼저 작성하여 실패를 확인하는 RED, 최소한의 코딩으로 테스트 통과를 확인하는 GREEN, 구현 및 설계를 리팩터링하며 테스트 통과를 유지하는 BLUE의 사이클로 이어지는 그림은 TDD를 이해하는 데 많은 도움이 되었다.
빨리 시도해보고 싶은 마음으로 개발해야할 것을 명확히 하지 않은 채 개발을 시작하면, 중간에 머리를 부여잡는 시간이 오는 경우가 꽤 있다. TDD는 테스트 코드를 작성하는 단계에서 목표를 명확히하는 것을 요구하여 이후 있을 고민 시간을 효과적으로 줄여줄 수 있다. 아무렴 초기의 변경이 더 쉬우니 말이다.
인터페이스를 어떻게 설계할 지, 어떤 단위로 테스트를 진행할 지, 테스트 더블을 어떻 게 사용할 지, Mockists인지 Classicists인지, 논리에 어떤 테스트 코드들이 있어야 거짓 음성이나 거짓 양성을 없앨 수 있을 지 등… 실제 활용 수준으로 들어가면 여전히 고민되고 어려운 부분은 많다.
각 프로젝트 상황에서 TDD 도입에 대해 어떤 트레이드오프가 있는지 따져보는 것은 여전히 매우 중요하다.
이론편에서 기억에 남는 내용
이론편에서 기억에 남는 내용
- Intro
반복되는 문제 해결에 비용이 많이 쓰이면, 지루하더라도 연습해서 생각의 비용이 줄어들도록 뇌에 새겨라
- 1-1 코드 기능 명세
도메인이란 SW가 풀어야 할 문제가 정의되는 공간이다.
프로그래머가 도메인의 모든 요소를 명확히 결정해서 알려주어야함.
- 1-2 테스트 기법
소프트웨어 회귀, 테스트 자동회, 인수 테스트, 단위 테스트
- 1-3 코드 분해
모듈의 구현이 아닌 인터페이스를 기준으로 조립한다.
자동화된 단위 테스트를 통해 제공하는 기능에 대한 신뢰감을 제공한다.
- 1-4 단위 테스트
- 1-5 테스트 우선 개발
어떤 목적으로 기능을 개발해야하는지를 명확하게 이해하기를 강요한다.
- 1-6 정리된 코드
리팩터링 전/후 기존 의미를 잘 유지하는 지 알기 위해서는 테스트가 필요하다.
- 1-7 테스트 주도 개발
TDD는 사실 버그 리포트 프로세스와 유사하다.
시스템의 수명은 언제까지인지 판단하여 TDD의 도입 여부를 결정해야 한다.
- 1-8 프로그래머 피드백
짧은 주기로 지속되는 피드백을 기반으로 안정적으로 코드를 작성하고, 지식을 늘릴 수 있다.
TDD는 요구사항이라는 가장 중요한 목표 달성을 유도하여 불필요한 자원의 낭비를 방지한다.
- 2-1 인터페이스와 구현
대부분 시스템 정보는 대부분의 프로그래머에게 가능하면 숨겨지는 것이 도움이 된다.
설계할 때는 어렵거나 변경될 여지가 있는 모듈부터 설계하라.
- 2-2 환경 변화와 적응력
모듈화로 인해 환경변화에 대응해야 할 시스템의 범위가 작아질 수 있다.
다형 성을 기반으로 한 OCP
- 2-3 입력과 출력
- 2-4 테스트 더블
대역 코드가 DOC와 동일하게 준수할 것이라고 가정하고, DOC가 SUT에 제공하는 인터페이스를 준수하는 대역 코드(Test Double)를 사용한다.
- 2-5 Mockists vs Classicists
Solitary 테스트
테스트 더블을 사용해 외부 의존성을 제거하고, 테스트 대상 객체나 함수의 단일 동작을 검증하는 데 중점을 둔 단위 테스트.
Sociable 테스트
테스트 대상과 실제 의존성(또는 필요한 일부 대체 객체)을 포함하여, 여러 구성 요소 간 상호작용과 동작의 일관성을 검증하는 통합 테스트.
Mockists
Mock 객체를 사용하여 행위 검증을 수행하고, 객체 간 상호작용이 명시적인 계약에 따라 이루어지는지 확인하는 접근법. 이는 설계에서 느슨한 결합을 유도하지만, 테스트가 종종 구현 세부 사항에 의존하게 되는 위험이 있다.
Classicists
시스템의 최종 상태를 검증하는 데 중점을 두며, 객체 간의 세부적인 상호작용(예: 호출 순서)을 명시적으로 검증하지 않는 테스트 방식.
- 2-6 Should I test private methods
private 코드를 테스트하게 되면, 테스트 코드가 내부 시스템 구현에 의존하는 강결합을 가진다.
- 2-7 테스트 주도 설계
TDD를 따름으로써 좋은 설계를 얻을 수는 없다.
테스트 작성이 쉽다고 해서 실제 구현 코드 구조가 잘 되어 있진 않을 수 있다.
- 2-8 테스트 주도 개발 의 한계
목표가 불명확한 상태에서 개발을 시작해야 할 때에는 테스트 작성 자체가 어렵고, 테스트 코드 작성 비용이 많이 들 수 있다.
- 2-9 인터페이스와 테스트
API는 코드 친화적 소통 수단으로, 변경도 보수적이기 때문에 테스트 자동화 비용이 낮다
UI는 인간 친화적 소통 수단으로, 변경도 잦기 때문에 테스트 자동화 비용이 높다
- 2-10 인수 테스트 주도 개발
인수 테스트에 실패한 단위에 대해 단위 테스트를 작성하는 방식으로 TDD를 진행한다.
- 2-11 코딩 계획
코딩은 하위 문제에 집중하게 만들기 때문에 명확한 이정표가 없다면, 길을 잃고 자원을 낭비하게 될 수 있다.