0. 테스트 코드와 TDD에 대한 나의 오해
TDD는 테스트 주도 개발 (Test-Driven Development)의 약자로, 소프트웨어 개발 방법론 중 하나입니다. TDD는 먼저 자동화된 테스트 코드를 작성하고, 그 테스트를 통과하는 실제 코드를 작성하는 방식을 사용합니다. 즉, 테스트를 먼저 만들고, 그 테스트를 통과하도록 코드를 작성하는 방식으로 개발을 진행합니다.
항상 이상을 꿈꾸는 개발자로서 테스트 코드, TDD에 대한 얘기는 익히 들었다.
“TDD를 하면 개발이 더 쉽다.”, “테스트 코드 덕에 리팩토링할 때도 좋다.”, “생산성이 향상된다.”
이 장점들은 이해를 할 수가 없었다.
테스트 코드의 작성은 어려웠고,
버벅거리며 작성해본 테스트 코드는 메서드를 수정할 때 몇 배의 수정을 겪어야 했다.
작성해야하는 코드의 양이 늘어 생산성이 저하된다고 느껴졌다.
단순 테스트 코드 작성도 어렵게 느껴졌는데, 테스트 코드를 먼저 작성한다는 매커니즘은 정말 이해하기 어려웠다. 일단 돌아가지 않는 코드를 작성한다는게.. 그래도 되는걸까?
- 커밋은 꼭 돌아가는 단위로 하랬는데?
- 어떤 클래스와 메서드를 만들줄 알고 테스트를 예상해서 만드냐?
(그 무렵의 TDD 상상도, 빨간줄이 가득하다.)
참 웃기게도 “실패하는 테스트 코드를 먼저 작성한다.” 라는 TDD의 시작을, “돌아가지만 실패하는 코드"가 아니라 “돌아가지도 않는 코드"를 작성하는 것이라고 생각했고, 이를 먼저 커밋하는 줄로 알았다. 약간은 바보같은 오해로 시작했지만, 이제 오해를 풀고 테스트 코드와 TDD에 입문해보자.
이번 글은 이 오해가 어떻게 풀렸는지, 그리고 TDD에 실제로 입문하며 얻은 깨달음을 정리한 기록이다.
1. 테스트에 대한 흔한 오해
오해 | 왜 그렇게 생각했는가? |
---|---|
테스트 코드 작성은 어렵다 | 어떤 케이스를 검증해야 할지 떠올리기 어렵다. 어노테이션, Mock, Stub… 생소한 도구와 개념이 넘쳐났다. |
리팩토링이 더 힘들다 | 메서드 하나 고쳐도 테스트까지 죄다 수정해야 했다 |
코드량이 늘어 생산성이 떨어진다 | ‘같은 기능 + 테스트’ → 두 배 작성량으로 보였다 |
2. 오해 풀어보기
2-1. 테스트 케이스는 “명세"로 부터 자연스럽게 나온다.
테스트 코드의 작성은 어렵다.
테스트 코드를 작성하기 위해서는 테스트를 위한 어노테이션들과 Mock
, Stub
, Spy
등의 새로운 개념들과 사용법도 익혀야한다.
여기까지만 어렵다. 여기부터는 오히려 쉽다. 이럴 땐 TOP-DOWN 방식의 사고가 꿀팁이 됐다. 명세를 기반으로 하면 된다. API 명세를 생각하면, 테스트 케이스는 절로 나온다.
그리고 백엔드 개발자들은 API의 귀재, CRUD의 왕이다.
포인트 충전 API를 예시로 들어보자.
요구사항
- 회원으로 존재해야 한다.
- 로그인이 되어야 한다.
- 충전 금액은 n원 이상부터 가능하다.
- 충전이 끝나면 현재 포인트를 반환해준다.
그럼 테스트로 검증해야 할 항목을 뽑기는 너무 쉽다. 이미 4개의 테스트 케이스가 머리에 스친다.
1. 회원이 아니면 401
2. 로그인하지 않으면 401
3. 100원 미만이면 400
4. 정상 충전 → 잔액이 N만큼 증가
결론: 테스트를 어떻게 짤까? 가 아니라 “명세를 어떻게 검증할까” 로 사고가 전환되자 작성 부담이 확 줄어든다.
2‑2. 수정/리팩토링이 두려운 진짜 이유는 “확신 부재"였다.
“잘 돌아가면 건드리지 말고 냅둬라.” - 우리가 수정을 두려워 하는 이유는 뭘까?
수정/리팩토링으로 인해 “보이지 않는 무언가(InvisibleSomething)“에서 발생한 오류로 서비스가 중단되고 책임의 대상이 되는 것이 두렵다. 고친게 잘 돌아갈지 확신이 서질 않는다. 테스트 코드가 있다면 리팩토링이 더 쉬워진다. 테스트 코드로 인해 수정해야 할 코드의 양이 많아진다고 하지만, 그로 인해 돌아간다는 “확신"을 얻을 수 있다. 확신을 얻을 수 있다면 테스트 코드의 몇 줄을 수정하는 정도야 값싼 트레이드오프다.
테스트 코드가 있을 때의 수정/리팩토링은 사실은 어려운게 아니라 양이 조금 많아질 뿐이다.
리팩토링을 하고 잘 돌아감을 확인하는데 까지 5분도 안걸렸다. (commit 로그에 오타 있음ㅠ)
2‑3. 작성할 코드는 늘어나지만 개발 속도는 빨라진다.
물론 코드의 양은 늘어난다.
다만, TDD처럼 실패와 성공 케이스를 미리 작성한 후 로직을 작성한다면 고민의 범위가 많이 줄어들 수 있다.
이건 어쩌지 또 저건 어쩌지? 고민고민하지 말고 테스트 코드를 믿고 하라는 것만 해보자.
~하면 실패
, ~하면 성공
테스트에 정리된 내용들을 보면서 개발하면 고민없이 코드가 술술 나온다.
테스트 코드 덕에 Postman을 왔다리 갔다리 하는 ContextSwitching이 굉장히 줄어든다.
최근 ADHD가 있는걸까 고민했는데 IDE 안에서만 작업하니 집중이 잘 되는 느낌이다.
(여담: 첫 주 미션을 수행하는데 Postman을 한 번도 쓰지 않았다.)
서버를 재시작 하고 수정하고 재시작하고, 구닥다리 회사 PC는 오늘도 굉음을 내며 돌아간다.
테스트 코드를 통해 개발하면 서버 재실행에 대한 부담이 적다. 특히 단위 테스트는 정말 가볍고 빠르다. 말 그대로 “딸-깍"으로 작성한 내용들을 검증해볼 수 있다.
테스트 코드를 작성해
- 작성 파일 수는 늘었지만, 컨텍스트 스위칭이 대폭 감소했다.
- 서버 재기동/Postman 왕복이 사라지니 순수 로직 구현 시간이 오히려 줄었다.
- 테스트 코드 요구 사항만 바라보며 작성하니 로직에 대한 고민 시간도 줄었다.
3. 마무리
TDD는 도구와 규칙이라기보다 사고 방식이라는 생각이 들었다.
“테스트를 먼저 작성한다.“는 행동이 중요한 것이 아니라, 의도를 작성하고 실패하는 과정을 눈으로 확인하고 성공을 반복한다는 루프가 핵심이다.
(이런 소소한 성취감은 삶의 만족도에도 긍정적인 영향을 미친다고 한다.)
처음엔 삽질처럼 느껴질 수도 있겠지만, 작은 API 하나라도 TDD 사이클로 완주를 해본다면, 빨간 불의 스트레스 보다는 초록 불이 주는 확신이 훨씬 크게 느껴진다.
누군가 이 글을 본다면 TDD 한번 해보시길…
thanks to loopers..