Computer >> 컴퓨터 >  >> 프로그래밍 >> Ruby

RailsConf 이후에도 여전히 TDD를 배워야 할까?

필자는 TDD(테스트 주도 개발)에 대해 수없이 많은 글을 써왔습니다. 그래서 지난번 글을 거의 정확히 같은 시각에 발행했는데, 마침 David Heinemeier Hansson(DHH)이 RailsConf 기조연설에서 TDD를 언급하면서 몇 가지 질문이 들어오기 시작했습니다.

DHH의 TDD에 대한 견해에 동의하시나요? 아직도 TDD를 추천하시나요? 아니라면 무엇을 해야 하죠?

DHH가 말한 것들

기조연설을 놓쳤다면, DHH가 작성한 에세이가 핵심을 잘 담고 있습니다.

아마도 테스트 우선 방식은 업계 전반의 자동화된 회귀 테스트 부재라는 안타까운 현실을 뒤집기 위한 직관에 반하는 돌파구로 필요했던 것일 겁니다. 어쩌면 소프트웨어 작성의 일상적인 과정을 문자 그대로 묘사하기보다는 하나의 우화였을지도 모르죠. 하지만 시작이 어떠했든, 곧 왜곡되고 말았습니다. 비신자들을 두들겨 패고, 그들을 비전문가이자 소프트웨어를 작성할 자격이 없는 사람으로 규정하는 망치로 사용된 것이죠. 일종의 리트머스 시험지처럼요.

이제 그만입니다. 더 이상은 안 됩니다. 나는 데이비드이며, 테스트 우선으로 소프트웨어를 작성하지 않습니다. 더는 그것에 대해 사과하지 않을 것이고, 숨길 생각도 없습니다. TDD가 자동화된 회귀 테스트의 눈을 열어준 것에는 감사하지만, 설계 교리로서의 TDD에서는 오래전에 벗어났습니다.

그렇습니다. 저에게 테스트 우선 방식은 끝났습니다. 하지만 그 무덤 위에서 춤추기보다는, 그것이 남긴 공헌을 기리고 저질스러운 논란에 매달리지 않겠습니다. TDD는 우리 역사에서 중요한 한 시기를 표시했지만, 이제 앞으로 나아갈 때입니다.

전체 글을 읽어볼 가치가 충분하지만, 주요 포인트를 정리하면 다음과 같습니다.

  1. TDD는 자동화된 회귀 테스트를 장려하기 위한 일종의 '마인드 핵(mind hack)'이다
  2. 공격적인 테스트 우선주의 수사는 슬픔과 절망만 낳는다
  3. TDD는 지나치게 복잡한 객체 얽힘과 간접 참조(indirection)로 이어진다
  4. 단위 테스트보다 고립된 시스템 테스트를 선호해야 한다
  5. 하지만 그 선호를 또 다른 종교로 만들면 안 된다
  6. 그런 이유로, 테스트 우선 방식은 더 이상 사용해야 할 설계 실천법이 아니다

에세이에서 이 주장들은 대부분 서로 얽혀 있습니다. 각각 따로 보면 일리가 있지만, 실제로는 그렇게 밀접하게 연결되어 있지 않습니다.

이 논점들을 분리하지 않으면, 하나의 논점에 대해 논쟁하는 순간 실제로 동의하지 않을 수 있는 다른 논점까지 함께 받아들이게 됩니다. 여기에 트위터의 분노와 140자 제한까지 더해지면 혼란, 허수아비 논리(strawman), 그리고 화염전(flame war)으로 번지게 되죠.

그래서 필자는 이 논점들을 몇 가지로 나누어 따로 살펴보려 합니다.

TDD는 지나치게 복잡한 객체 구조로 이어진다는 주장

최근 Ruby 테스팅 커뮤니티에서 '복잡한 객체 얽힘과 간접 참조'에 대한 선호가 눈에 띕니다. 필자는 이것이 좋지 않다고 생각합니다. (필자가 처음에 Java에서 도망친 이유 중 하나이기도 하죠!) 하지만 그 원인이 TDD라고는 생각하지 않습니다.

필자는 거의 10년 가까이 TDD를 해왔지만, 테스트를 데이터베이스로부터 고립시키지 않았습니다. 컨트롤러 수준의 기능 테스트와 탄탄한 통합 테스트 스위트도, 아무리 느리게 실행되더라도 전체 테스트 스위트에서 소중한 부분입니다.

테스트를 시스템으로부터 고립시키는 것은 어디까지나 최적화 작업일 뿐입니다. YAGNI(You Aren't Gonna Need It) 원칙에 따르면, 아직은 그리 중요하지 않을 가능성이 높습니다. 게다가 개별 테스트를 일일이 최적화하는 것보다 SSD나 앱 프리로딩으로 전반적인 속도 향상을 얻는 편이 훨씬 낫습니다.

물론, TDD가 시스템 설계에 영향을 미치는 것은 사실입니다.

TDD는 코드를 유기적으로 성장시킵니다. 이건 대단히 좋은 점이 될 수 있습니다! 하지만 때로는 숙련된 개발자가 TDD가 만들어낼 것보다 더 나아 보이는 코드를 직접 작성할 수 있습니다. 다른 코드와 더 단단하게 결합되어 있거나 OOD(객체지향 설계) 원칙을 모두 따르지 않을 수 있지만, 명확하고 직관적이며 단순한 코드죠. (DHH Ping Pong에 좋은 예시들이 있습니다.)

또한 TDD는 정작 무엇을 만들고 있는지 제대로 파악하기도 전에 객체 API 설계에 갇히게 만들 수 있습니다. 이후에 API를 변경하기가 더 어려워지죠. 그리고 그 마찰 때문에 더 나쁜 설계에 안주하게 될 수도 있습니다.

'테스트 우선은 더 이상 쓸 설계 실천법이 아니다'라는 주장

TDD는 유연하고 잘 테스트된 코드를 만들기 위한 훌륭한 도구입니다. 그래서 이 주장에는 전적으로 반대합니다. TDD의 많은 장점들은 이미 이전 글에서 다룬 바 있습니다.

  • 더 유연하고 테스트가 검증된 객체 모델을 갖게 됩니다.
  • 시스템이 정의상 테스트 가능하므로, 이후 테스트 작성 비용이 줄어듭니다.
  • 테스트 비용을 개발 과정 전반에 분산시켜, 추정치가 더 정확해집니다.
  • 다음에 무엇을 해야 할지 고민할 필요가 없으므로 흐름(flow) 상태가 유지됩니다.

이러한 장점 외에도 TDD는 테스트를 연습하는 데 큰 도움이 됩니다. 항상 테스트를 먼저 작성하기 때문에, 사후에 테스트를 작성하는 경우보다 훨씬 많은 테스트를 하게 됩니다. 또한 테스트가 실제로 올바른지 즉시 알 수 있습니다(테스트가 먼저 실패하니까요). 게다가 "이번 한 번만" 테스트를 건너뛸 명분도 생기지 않습니다.

공격적인 테스트 우선주의 수사 문제

이 부분에는 100% 동의합니다. 네, 같은 말을 또 하는 겁니다. 하지만 누군가 TDD의 장점을 몰라서, 아직 방법을 배우지 못해서, 혹은 불편함을 느껴서 TDD를 하지 않는다면 올바른 대응은 그들을 창피 주는 것이 아니라 돕는 것입니다. TDD가 유용하다면 어떻게 도움이 되는지 보여주세요. 관심을 보인다면 시작할 수 있도록 도와주세요.

만약 TDD 없이 만들어지는 코드의 결과물을 더 선호해서 TDD를 하지 않는 것이라면, 그대로 두세요.

전문성을 쌓아가다 보면 자신만의 직관, 자신만의 취향, 그리고 소프트웨어 개발을 위한 자신만의 선호 기법이 생깁니다. 그리고 어떤 인터넷 논쟁도 전문가에게 그런 것들을 무시하라고 강요할 수는 없습니다.

결국, 자신의 기준에 맞지 않는다고 비판한다면 상대방의 학습 능력을 해치거나, 아니면 허공에 대고 외치는 것과 같습니다. 최선의 경우 시간 낭비이고, 최악의 경우 당신의 주장 자체를 해치는 것이죠.

그래서, 계속 TDD를 해야 할까?

네! 배우고 연습할 것을 강력히 권합니다.

필자가 테스트하는 법을 배운 것은 TDD 덕분이며, 지금도 TDD를 활용하면 큰 이점을 얻습니다. 물론 완벽하지는 않지만, 더 나은 코드를 마법처럼 만들어주는 단 하나의 기술이라는 것은 세상에 존재하지 않습니다.

대신 새로운 패턴, 기술, 도구를 계속 배워야 합니다. 올바른 패턴을 올바른 위치에 사용할 때 직감적으로 맞다고 느껴질 때까지 연습하세요.

배우는 과정에서 코드를 수정하고, 리팩토링하고, 실험해볼 시간을 가져보세요. 예전 코드와 새 코드를 비교해보세요. 경험이 더 많은 사람에게 리뷰를 요청해보세요. 더 나아졌나요? 그것이 성장하는 방식입니다.