원문: Thomas Heijtink, "TDD and the scientific method"
소개
TDD와 관련한 대부분의 논의는 "Testing"에 집중되어 있는 듯합니다. 아무래도 이름의 탓(?)이 아닐까 하는데요. "마이크로 서비스"와 같은 주제에서 대부분의 사람들이 서비스 자체의 크기에만 집중하듯 TDD의 이름 자체가 "Testing"에서 왔기 때문일 것입니다.
다른 분야에서도 마찬가지일지는 모르겠으나 소프트웨어 공학에서는 이렇듯 이름이 중요합니다. 실제로 소프트웨어 엔지니어들은 이름을 짓는 데 많은 시간을 씁니다. 그런데 그 과정에서 그 이면에 있는 아이디어를 놓치는 경우가 있습니다. 따라서 이름을 짓는 것 자체도 어렵지만 이름 이면의 컨셉트를 파악하는 것이 더 어렵다고 할 수 있겠습니다.
이와 같은 맥락에서 TDD를 논할 때 "Tests"에 초점을 맞추게 되곤 하는데요. 그럼에도 불구하고 이름이 개념의 모든 중요 측면을 포괄하는 경우는 드뭅니다. 이름은 항상 특정 맥락과 특정 이용자들에게만 의미가 있고 맥락과 이용자들이 변하면 이름의 의미도 바뀔 가능성이 높기 때문입니다.
저는 숲의 관점에서 개념을 바라보는 것을 좋아하기 때문에 개념이 탄생하는 큰 그림과 목표 등을 중시합니다. 따라서 이러한 관점에서 TDD를 어떻게 바라보게 되었는지를 알려드리고자 합니다.
현실
소프트웨어 엔지니어는 문제가 일어나는 현실을 이해해야합니다. 이 문제란 우리가 달성하고자 하는 목표의 산물이고 그 목표를 달성하고자 하는 상황과 대상에 따라 더욱 구체화됩니다. 결국 목표가 없으면 문제도 없습니다. 또한 이용자가 없으면 목표도 없습니다. 문제는 상황에 따라 다르기에 소프트웨어 엔지니어링에는 정답이 없습니다. 다만 자신의 상황에서 목표나 대상을 살피고 연구하는 방법은 올바른 방향을 알아내는 데 도움이 됩니다.
이렇게 말씀드리는 이유는 TDD가 관행이나 규율보다는 문제를 해결하는 방향에 가깝다는 점을 말씀드리고 싶었기 때문입니다. 관행과 규율은 오히려 문제를 해결하고자 하는 사고방식에서 나온 산물에 가깝습니다. 따라서 무엇을 해야할지 규정짓는 것이 우선이라고 생각하지는 않습니다만 방향과 관련해서는 이 글이 도움을 드릴 수 있을 것 같습니다.
마인드셋
과학적 방법은 적어도 마인드셋의 과정을 잘 설명할 수 있을 것이라 생각합니다. 이는 반드시 TDD가 과학적 방식이라는 뜻이 아니라 과학적 방법은 TDD에서 가져야하는 마인드셋을 잘 설명해줄 것이라는 뜻입니다.
1. 관찰
관찰은 과학자들이 자연으로부터 관심가는 현상을 바라보고 식별하는 초기 단계입니다. 관찰은 직접적인 경험을 통하여 혹은 도구를 통해 수행할 수 있습니다.
2. 질문·문제 설정
과학자는 관찰을 바탕으로 조사하고자 하는 구체적인 질문이나 문제를 설정합니다. 이 단계는 연구에 초점을 맞추고 연구 목적을 정의하는 데 도움이 됩니다.
3. 가설
가설은 관찰된 현상에 대한 잠재적 설명을 말합니다. 테스트가 가능하고 검증이 가능한 진술이라 할 수 있습니다.
4. 실험
가설을 테스트하기 위한 실험을 설계하고 수행하는 단계입니다. 실험은 과학자가 데이터를 수집하고 결과를 분석할 수 있도록 신중히 통제됩니다. 실험을 하는 목표는 관찰된 결과가 가설을 지지하는지 혹은 반박하는지에 대한 여부를 결정하는 것입니다.
5. 데이터 수집
실험 진행 중 과학자는 관찰과 측정 혹은 다른 여러 방법을 통해 관련 데이터를 수집합니다. 수집된 데이터는 정확하고 신뢰할만하며 연구가 해결하고 싶어했던 질문과 관련이 있어야 합니다.
6. 분석
통계 혹은 기타 방법을 이용해 수집된 데이터의 패턴이나 추세, 관계 등을 분석합니다. 목표는 데이터에서 의미가 있는 결론을 도출하고 가설을 지지하거나 거부할지 여부를 결정하는 것입니다.
7. 결론
과학자는 분석 결과를 바탕으로 결론을 도출합니다. 데이터를 해석하고 가설과 관련된 결과가 어떤 의미를 가지는지 결정합니다. 가설이 맞으면 추가 연구나 기존 이론의 개선으로 이어질 것이고 그렇지 않으면 가설 수정이나 추가 실험을 수행하게 됩니다.
8. 커뮤니케이션
마지막 단계는 과학 커뮤니티 및 대중에 연구결과를 공유하는 것입니다. 이는 논문이나 프레젠테이션 혹은 여타 커뮤니케이션을 통해 이뤄지고 이 결과를 기반으로 다른 과학자들이 연구를 검토하고, 따르고, 발전시킬 수 있습니다.
이 8가지 단계가 TDD 사고방식의 목표라고 할 수 있겠습니다. 자동화된 테스트 이전에 이 모든 단계가 이뤄집니다.
실험이 과학적 방법의 네번째 단계라는 점에 주목하시면 좋겠습니다. 또한 관찰은 첫번째 단계라는 사실도요. 실험 이전의 3단계를 놓치면 테스트의 효과와 가치가 떨어지게 됩니다.
관찰
비즈니스에 보다 책임이 있는 사람들이 자주 수행하는 이 단계에서 전체 비즈니스 프로세스가 간소화된다거나 점검이 진행되고 완전히 새로운 프로세스들이 생겨날 수 있습니다. 소프트웨어 엔지니어들은 특정 문제 해결을 위해 관찰 단계의 중간 즈음에 참여하게 됩니다. 이때 TDD 마인드셋을 활용해야 합니다.
첫 번째 관찰 단계에서는 우선 특정 문제를 해결하기 위해 이미 누군가에 의해 관찰된 내용을 이해하려고 노력하게 됩니다. 이 과정에서 중요한 것은 지레 확신하지 않는 것입니다. 자신감이 넘치는 나머지 다른 사람이 했던 관찰이 부정확하다고 생각하여 사안을 잘못 이해하는 것을 원치 않으신다면 말입니다. 또한 관리자가 여러분과 공유하는 사안에 대한 맥락을 잃지 마시길 바랍니다. 이제 여러분은 첫 번째 관찰 단계에 있으며 언제 프로세스에 참여했는지에 따라 전체적인 이해가 부족하고 제한적일 수 있습니다. 최초 관찰자는 여러분들이 모르는 것을 이미 알고 있다는 것을 생각해 보세요.
가장 이상적으로는 여러분 혹은 관리자가 문제 해결에 관여할 사람들을 모아 팀을 꾸리고 어느 시점에 첫 회의를 하게 되는 것입니다.
많은 소프트웨어 엔지니어에게 관찰 단계는 무의식적로 흘러가는 과정이 될 것입니다. 즉, 이 단계를 최대한으로 활용하지 못하게 된다거나 관찰이 왜곡되는 중대한 실수가 발생할 수 있다는 뜻입니다.
왜냐하면 관찰 단계는 여러번 반복되기 때문입니다. 예를 들어 당면한 문제에 대하여 논의하기 위해 운영 전문가와 이야기를 할 때 가장 중요한 것은 그들이 하는 일을 이해하고, 왜 그렇게 하는지를 이해하는 것입니다. 다음은 구체적으로 그 단계가 어떻게 이뤄지는 지에 대한 사례입니다.
첫인상: 운영 전문가를 처음 만나면 이미 관찰을 시작할 수 있습니다. 판단은 우선 하지 마시고 관찰만 합니다. 일상적인 작업에 대하여 가지고 있는 지식을 살펴보고 해당 전문가가 주제와 관련한 데이터를 얼마나 쉽게 찾을 수 있는지에 대한 여부 등을 관찰합니다. 또한 그 사람이 사용하는 언어가 일관적이고 정확한가를 파악해보세요.
질문하기: 때로는 무엇인가를 이해하거나 명확히 하기위해 질문을 해야할 때가 있습니다. 이미 특정 답변을 포함하거나 암시하는 질문은 하시면 안됩니다. 가장 좋은 방법은 열린 질문을 하는 것이지만 다른 유형의 질문도 도움이 될 수 있습니다. 다양한 유형의 질문에 익숙해지면 관찰력이 향상되고 TDD 사고방식에 도움이 될 것입니다.
이벤트스토밍: 이 기법은 도메인과 현 비즈니스 프로세스를 더 잘 이해하는 데 도움이 되는 기법입니다. 여기서 전체 개념을 설명하지는 않겠습니다. 인터넷에 검색하면 더 훌륭한 자료와 예시를 찾을 수 있습니다.
질문·문제 설정
이 시점에서 어떤 문제를 해결할 것인지 공식화해야합니다. 이 단계에서 중요한 것은 범위를 결정하는 것입니다. 예를 들어 질문이나 문제를 한 문장으로 줄이는 것이 도움이 됩니다. 단락이나 에세이가 아닌 한 문장으로 말입니다. 한 문장으로 줄이면 핵심 문제에 집중하고 간결하고 정확한 언어를 사용하는 데 도움이 됩니다. 모든 사람이 정리한 문장이 문제의 본질을 다루는 것 같다고 동의할 때까지 필요한 만큼 자주 문장을 수정하는 시간을 가지세요. 여러 문장으로 정리된다면 이를 하나의 문장으로 통합할 수 있을지 혹은 어떤 문장에 먼저 집중해야할지를 물어보세요.
가설
이제 전통적 테스트 단계에 조금 더 가까워지는 단계입니다. 이 단계에서는 문제가 해결되었는지 혹은 질문에 대한 답이 올바른지, 어떻게 측정할 것인지에 대한 질문을 해야합니다. 이 단계를 통해 공식화된 문제를 해결하는 데 필요한 최소한의 기능이나 소프트웨어 기능 목록을 작성합니다. 이 모든 기능이 구축된 후에는 핵심 문제를 해결할 수 있을 정도여야 합니다.
너무 많은 세부 사항은 피하되 최대한 완벽하도록 노력해야 합니다. 먼저 운영 전문가가 자신의 언어로 기능을 공식화할 수 있게끔 합니다.
필요한 기능을 발견하는 데 도움이 되는 한 가지 관행이 있는데 이는 이벤트 모델링이라고 합니다. 이 방법이 유용한 이유는 매우 상세하고 구체적이기 때문입니다. 이벤트 모델을 공식화 하게되면 모델에서는 필요한 기능이 어느 정도 드러납니다.
다음은 기능을 구성하는 몇가지 방법입니다. (주의: 이러한 기능이 반드시 하나의 프로젝트와 연관된 것은 아닙니다).
회사 신입 직원 가입
신입 직원에게 시스템에 대한 액세스 권한 제공
직원을 팀과 직무에 할당
직원세부 정보 및 계약 변경
신입 직원을 위한 온보딩 프로그램 제공
관리자가 팀 내 동료의 개인 로그를 관리하도록 지원
이 목록에는 몇가지 중요한 사항이 있습니다.
- 각 기능이 동사라는 점에 주목하세요. 소프트웨어는 무엇인가를 해야 합니다. 소프트웨어의 행동에 따라 어떤 종류의 소프트웨어인지 결정됩니다. 따라서 어떤 데이터가 필요한지, 어떤 종류의 시스템이 필요한지보다는 동작에 초점을 맞추세요.
이는 일반적으로는 긴 목록이 아닙니다. 목록이 길수록 범위가 더욱 넓어지게 될 것입니다.
실험
실제로 테스트를 진행할 차례입니다. 이제 각 기능에 대해 해당 기능과 관련된 시나리오 또는 요구 사항을 논의하고 정하게 됩니다. 이와 관련한 시나리오 혹은 요구 사항의 예시는 다음과 같습니다.
"새 직원이 입사한다고 가정할 때 세부적인 내용이 필요합니다."
특정 시나리오의 세부 사항 ("given", "when", "then" 또는 "arrange", "act", "assert")을 정리하는 동안 답변이 필요한 몇 가지 질문을 발견하거나 누락된 기능을 발견할 수 있습니다.
이 단계에서는 발생 가능한 모든 시나리오를 다루기보다는 가장 필요하고 위험을 줄이는 것에 집중해야 합니다. 더불어 시나리오를 문서화하는 것도 중요합니다. 기능을 어떻게 바라보는지 명확히 하기 위해 시나리오를 추가하는 경우도 있습니다. 이러한 시나리오를 여러 번 반복하다 보면 결국 해당 시나리오를 삭제, 추가 또는 변경하게 될 것이고 기능이 실제로 어떤 내용인지 파악할 수 있을 것입니다.
운영 전문가와 함께 시나리오에 합의하면 각 요구 사항이 충족될 때까지 이러한 요구 사항을 구현하기 시작합니다. 첫 번째 기능 또는 몇몇 시나리오가 구현되면 소프트웨어를 출시하고 해당 기능과 시나리오가 실제로 비즈니스에서 찾고 있는 것인지, 해결해야 하는 초기 문제와 적절하게 일치하는지 실험해 봅니다.
데이터 수집
이 단계에서는 테스트 결과를 논의하고 기능이 어떻게 사용되는지 확인합니다. 말하자면 여러분과 운영 전문가가 제안한 가설이 적합한지 데이터를 수집하는 단계입니다. 너무 세부적으로 조정하지 마세요. 초기 문제 해결을 방해하는 부분을 기준으로 우선순위를 정하세요. 특정 "버그"는 나중에 해결할 수 있습니다. 그리고 나중에 특정 기능을 추가하여 소프트웨어를 더욱 안정적으로 만들 수 있습니다. 처음에 개발하고자 했던 가치를 제공한다면, 이 실험이 성공적이었다는 것을 알 수 있습니다. 이때 기능의 성공 여부는 발견된 버그 양이나 특정 시나리오의 누락 등으로 결정되는 것이 아니라 비즈니스에서 이 기능을 사용해 문제를 해결할 수 있는지에 달렸습니다. 만약 성공적으로 문제를 해결할 수 있었다면 실험은 성공한 것입니다.
분석
이 단계에서는 어떤 기능이나 시나리오가 적합한지, 어떤 기능이나 시나리오가 누락되었는지, 또 솔루션을 사용함으로써 새로운 인사이트를 얻었는지 분석합니다. 이 과정에서 이 기능이 필요가 없다는 것을 발견하거나 훨씬 덜 복잡한 버전을 생각해야 할 수도 있습니다. 혹은 새로운 기능을 생각해야 할 수도 있고 원점으로 돌아가야 할 수도 있습니다.
결론 도출
이 단계에서는 릴리스된 소프트웨어의 의미를 살펴봅니다. 그리고 다음 단계를 결정합니다. 계속 진행할 것인지, 개선할 것인지, 수정할 것인지, 아니면 처음부터 다시 시작할 것인지 결정합니다. 다시 관찰부터 시작해야 할 수도 있고 질문이나 문제가 결국 충분히 명확하지 않았을 수도 있습니다. 하지만 결국 가장 중요한 것은 소프트웨어의 원하는 동작을 설명하고 보호하기 위해 만들어졌던 자동화된 테스트가 남는다는 것입니다. 비즈니스 가치에 중점을 두고 복잡성과 위험을 테스트합니다.
커뮤니케이션
이 모든 과정을 통해 도움을 받을 다른 사람들과 결과를 공유하세요. 이 과정에서 그들의 질문이나 아이디어를 통해 도움을 받을 수도 있습니다.
최종 결론
이 글에서는 제가 TDD를 어떻게 바라보는지 설명하려고 노력했습니다. TDD는 단순히 테스트를 작성하는 방법이 아니라 사고방식에 가깝습니다. 즉 이는 접근 방식을 실행하는 데 사용하는 다양한 방법론보다는 작업에 접근하는 방식입니다. 이 사고방식으로부터 실질적인 방법들이 파생됩니다. 물론 이 방법들은 실제 솔루션으로 사용하기 위한 것이라기보다는 특정 아이디어를 탐색하기 위한 작은 프로그램일 뿐입니다. 예를 들면 소프트웨어 엔지니어와 형식이 없는 질문에 답하는 자동화된 요구 사항 테스트와 함께 Chat GPT를 사용할 수 있는지 알아보는 정도의 프로그램이 되겠습니다.
글을 간결히 작성하기 위해 저는 예제나 하위 단계 전부를 제공하지는 않았습니다. 여러분이 직접 이러한 사고방식을 구현해 보시면 제가 적어 놓은 것보다 훨씬 더 많은 것을 발견하실 수 있을 것이라 믿습니다.
마지막으로 사람들은 과학적 방법의 여러 단계에 따라 저와는 또 다르게 TDD를 분류할 수 있다는 점을 말씀드리고 싶습니다. 비유는 비유일 뿐 완벽하게 같은 것이 아닙니다. 오히려 제가 생각하는 TDD 사고방식의 다양한 측면을 논의하기 위한 청사진이 될 뿐입니다. 예를 들어 DMAIC 방법도 TDD 사고방식에 적용할 수 있는 것처럼요.