관리 메뉴

제뉴어리의 모든것

[Agile] TDD(테스트 주도 개발)란 본문

CS

[Agile] TDD(테스트 주도 개발)란

제뉴어리맨 2021. 4. 3. 01:01

 

Goal

  • TDD의 정의 - ‘결정과 피드백 사이의 갭을 인식하는 것’을 이해할 수 있다.
  • TDD의 효과 - TDD는 언제, 어떻게 사용하면 좋을까
  • TDD를 활용하기 어려운 이유와 잘 하는 방법
  • 프로그래머 외의 사람들에게는 TDD는 어떤 의미가 있을까



[들어가기 전]

  • TDD가 프로그래머에게만 해당한다고 생각하면 애자일의 근본 개념을 망치는 것이다.
    • 모든 직무에서 TDD를 적용할 수 있다.
  • 또한 TDD의 ‘진짜’개념을 적용하기 위해서는 많은 시간이 걸릴 것이다.
    • 우선 아래의 내용을 통해 TDD에 대한 통찰을 얻어보자.

TDD란

TDD의 정의

  • Test Driven Development
    • 테스트 주도 개발: 테스트가 개발을 이끌어 나간다.

구체적인 행동 레벨에서의 TDD의 개념

테스트를 먼저 만들고 테스트를 통과하기 위한 것을 짜는 것 즉, 만드는 과정에서 우선 테스트를 작성하고 그걸 통과하는 코드를 만들고를 반복하면서 제대로 동작하는지에 대한 피드백을 적극적으로 받는 것이다.

  • 보통은 SW 개발을 할 때 코딩을 다 끝나고 난 후 테스트를 한다.
    • 코딩이 끝난 후? 개발자가 코딩을 다 짜고 난 후 완성했다고 생각할 때
    • 이것의 순서를 바꾸는 것이 TDD를 적용하는 것이다.
  • TDD를 적용한 사례
    • 예를 들어, 생년월일(input)을 입력받으면 현재 나이(output)를 출력하는 프로그램
    1. 처음에는 간단한 것으로 목표를 정한다. (태어난 해와 올해의 연도를 입력)
      • 2015, 2018 -> (만)3살 우선 이것을 만들겠다는 생각을 한다.
    2. 만들기도 전에 만든 후에 무엇을 테스트할지를 설계한다.
      • 2015, 2018를 입력하면 2가 나오는 테스트 프로그램(장차 만들 프로그램을 테스트할 코드)를 만든다.
    3. 그 다음에 그 테스트를 통과할 프로그램(1.을 목표로 작성한 코드)를 만든다.
      • 올해의 연도 - 태어난 해
      • 2018 - 2015
    4. 테스트 프로그램으로 이 프로그램(3.에 해당하는 코드)을 실행한다.
    5. 통과했으면 새로운 테스트를 추가한다.
      • 이번에는 생월을 추가했을 때 계산하는 프로그램
    • 위와 같은 작업을 계속 왔다갔다 수행한다.

추상적인 레벨에서의 TDD의 핵심 개념(중요)

결정과 피드백 사이의 갭에 대한 인식, 더 나아가 결정과 피드백 사이의 갭을 조절하기 위한 테크닉이라고도 할 수 있다.

  • 켄트 벡(Kent Beck, 익스트림 프로그래밍의 창시자)
    • TDD란?
      1. 결정과 피드백 사이의 갭에 대한 인식
      2. 결정과 피드백 사이의 갭을 조절하기 위한 테크닉
    • TDD는 프로그래밍 기법이나 기술적인 느낌보다는 심리적인 것으로 볼 수 있다.
  • 결정(decision)?
    • 프로그램을 하다보면 ‘이 방법으로 해야지’, ‘이 부분은 이걸 이용해서 짜야지’라는 것을 결정한다.
  • 피드백(feedback)?
    • 프로그램을 하다보면 성공/실패(에러)라는 피드백을 받는다.
  • 이 둘(결정과 피드백) 사이에 갭이 생긴다.
    • 갭이 커질수록 문제!
    • 내가 그 갭을 모르면 더 큰 문제!
    • 즉, 위의 예와 함께 설명하자면
      • 결정: 1.을 목표로 코드를 작성할 때, ‘나는 빼기로 나이를 구해야겠다.’라는 것을 결정한다.
      • 피드백: 빼기로 계산했을 때의 코드를 테스트 프로그램을 실행한 결과로, 된다/안된다라는 프로그램 상의 피드백을 받는다.
      • 이 둘 사이의 갭을 내가 인식한다면 TDD를 하고 있는 것이다.

TDD의 효과

TDD를 왜 해야할까

애자일이란에서 설명한 것과 같이 불확실성이 높을 때 ‘피드백’과 ‘협력’이 중요하다.

  • 피드백과 협력이 중요한 이유
    • 불확실성이 높을 때 ‘피드백’과 ‘협력’을 이용하면 더 좋은 결과가 나올 확률이 높아진다.
    •  
    • TDD도 마찬가지로 ‘피드백’과 ‘협력’을 증진시키는 것이기 때문에 불확실성이 높을 때 도움이 되는 것이다.

TDD는 어떤 상황에서 해야할까

  • 만약 어떤 부분에 대한 코딩을 여러번 해봤고 결과가 어떻게 나올지 뻔하다면 TDD를 하지 않아도 된다.
  • 또한 TDD를 했을 때 얻는 것이 적다면 TDD를 하지 않아도 된다.
  • 그렇다면 TDD는 어떤 상황에서 해야할까?
    1. 처음해보는 프로그램 주제
      • 나에 대한 불확실성이 높은 경우
    2. 고객의 요구조건이 바뀔 수 있는 프로젝트
      • 외부적인 불확실성이 높은 경우
    3. 개발하는 중에 코드를 많이 바꿔야 된다고 생각하는 경우
    4. 내가 개발하고 나서 이 코드를 누가 유지보수할지 모르는 경우
  • 즉, 불확실성이 높을 때 TDD를 하면 된다.

TDD의 효과

모든 애자일의 실천법은 피드백과 협력을 동시에 증진시킨다.

1. 피드백

  • TDD를 하면 피드백이 증가한다.
    • 테스트를 통과하는 것으로 잘되고 있는가를 자주 확인할 수 있다.
    • 이 부분은 사람들이 쉽게 느낄 수 있다.

2. 협력(이 부분이 핵심!)

  • 켄트 벡(Kent Beck)
    • ‘test’는 일반적으로 동사로 사용한다. ‘테스트한다.’, ‘테스트해라.’
    • 예를 들어, 누가 나한테 생년월일(input)을 입력받으면 현재 나이(output)를 출력하는 프로그램을 주고 test해보라고 한다면 내가 할 수 있는 것은 숫자를 여러 개 찍어보는 것이다.
      • 태어난 시간과 지금 시간이 같으면 0
      • 태어난 시간이 더 미래의 시간이면 ‘출생 전’
      • 등등
    • 그러나 TDD를 하면 ‘test’는 명사가 된다.
  • ‘test’가 명사가 되면?
    • 동사는 그 순간에만 하는 것이고, 명사(대상, 목적어)는 이후에도 소유할 수가 있다.
    • 즉, record로 남을 수 있다.
    • ‘test’가 저장된다는 것은 남들에게 남들에게 테스트 코드를 보여줄 수 있고, 남들은 그 코드를 직접 실행해볼 수 있다는 것이다.
  • 그렇다면 TDD는 왜 협력을 증진시키는가?
    • ‘test’가 명사(대상, 목적어)가 되는 순간 이것을 공유하기가 쉬워진다.
    • 공유하면 협력이 증진된다.
      1. 남이 짠 코드를 빨리 이해할 수 있다.
      2. 남이 짠 코드를 쉽게 이해할 수 있다.
      3. 용기가 생긴다.(내가 남의 코드를 고쳐서 문제가 있더라도 자동화된 테스트가 알려주기 때문에 큰 걱정없이 고칠 수 있는 용기가 생긴다.)
        • 내가 이 코드를 고쳤을 때 이것을 망치면 어떡하지..
        • 내가 그 사람의 의도를 모르는데 이것을 고쳐도 될까..
  • 즉, 왜 이렇게 짰을까 궁금할 때 ‘test’를 공유하고 그 테스트 코드를 보면 이해할 수 있다.
  • 테스트 코드에는 개발자의 개발 과정(어떤 고민/어떤 의사결정)이 나와있기 때문이다.
  • 앞의 TDD의 정의(결정(decision)과 피드백(feedback) 사이의 갭을 인식하는 것)와 같이 테스트 코드(feedback)를 보면 그 사람의 의사결정(decision)이 나타나고 상대방은 그 부분은 왜 그렇게 짰는지를 쉽고 빨리 알게 되기 때문에 협력이 증진된다.

TDD의 장단점

그렇다면 TDD는 왜 좋을까

피드백과 협력을 증진시키기 때문에 불확실성에 대해 대비를 하게 해준다.

  • 개발속도가 느려진다고 생각하는 사람이 많기 때문에 사람들은 TDD에 대해 반신반의 한다.
    • 처음부터 2개의 코드를 짜야한다.
    • 중간중간 테스트를 하면서 고쳐나가야한다.

TDD의 장단점

  • 연구 논문 결론 취합
  1. TDD를 하면 개발 시간이 늘어난다.
    • 개발 시간의 정의?
      • 본인이 ‘다했다고’생각할 때까지, 기능 구현이 끝났을 때까지
    • 개발 시간이 TDD를 하지않을 때에 비해 대략 10~30%가 늘어난다.
  2. TDD를 하면 결함이 줄어든다.
    • 결함이 1/2~1/10 까지 줄어든다.
    • SW를 개발하면서 예상하지 못했던 시간을 많이 소요하는 것은 대부분이 버그 때문이다.
    • TDD를 하면 이런 버그를 줄일 수 있다.
  3. TDD를 하면 코드 복잡도가 떨어진다.
    • 엔트로피(Entropie)가 낮아진다.
    • 깨끗한 코드 가 나온다.
    • 유지보수 비용이 낮아진다.
  • cf. 복잡도에 대한 재미있는 연구
    • 복잡도에 대해 수치로 계산할 수 있다.
    • 들여쓰기(Indent)가 많은 코드는 복잡한 코드이다.
    • 복잡성 지표(Cyclomatic Complexity)를 통해 들여쓰기에 따라 복잡도를 숫자로 계산한다.
    • 계산한 복잡도가 일정 수치 이상이 넘어가면 버그를 고칠 때 나도 모르게 버그를 삽입할 확률이 1에 수렴한다.
      • 즉, 내가 버그 하나를 고치려고 그 코드를 고쳤는데 나도 모르게 새로운 버그를 넣는 확률이 1에 수렴한다는 것이다.
    • 복잡도가 높으면 버그 숫자가 줄지 않는다.

TDD를 활용하기 어려운 이유와 잘 하는 방법

왜 다들 TDD를 활용하지 못할까? TDD를 하기 여려운 이유는 무엇일까?

  1. 개발 시간이 증가한다.
    • 많은 기업들이 단기적인 성과에 집중해 있다.
    • 전체 개발 시간을 줄이는 것보다 오늘 일을 끝내는 것을 강조하기 때문에 TDD 도입이 어렵다.
    • 단기적인 것에 집중되어 있으니.. 그때까서 또 고치면 되니까.. 고객이 화내면 안되니까.. 급한 불을 끄면서 허덕이면서 살기 때문에..
  2. TDD가 어렵다.
    • 왜?
      • 이제까지 자신이 개발하던 방식을 많이 바꿔야 하기 때문에
    • 몸에 체득한 것이 많을수록 바꾸기가 어렵다.
      • 언러닝(Unlearning): 이미 배운것을 까먹는 과정
    • TDD는 오히려 개발을 별로 안해본 사람에겐 적용하기가 쉽다.
  3. TDD는 이렇게 해야된다는 이미지/틀이 있다.(핵심)
    • ‘반드시 툴(단위 테스트 프레임워크)을 써서 이렇게 해야된다.’라고 생각한다.
    • 하지만 이런 규칙에 얽매이는 것은 애자일이 아니다.
    • 결국엔 규칙에 얽매여 똑같은 테스트를 copy&paste 한다.
    • 너무 도구/규칙에 집착하니까 TDD가 어려워지는 것이다.

TDD를 잘하는 방법?

적응적, 진화적으로 접근해야 한다.

  • 나 스스로 ‘어떻게 해야 피드백을 더 자주 받을까’, ‘어떻게 해야 내가 하는 작업에 대해 협력이 잘 일어나게 할까’를 고민하면서 계속해서 내가 일하는 방식을 업그레이드 해야한다.
  • 예를 들어, 게임을 개발하면서 stage 3을 테스트할 때
    • 항상 stage 1, stage 2를 클리어한 후 테스트를 해야 한다.
      • 테스트 비용이 증가한다.
      • 어떻게 하면 테스트 비용을 낮출수 있을까를 고민한다.
    • 바로 stage 3으로 갈 수 있도록 만든다.
      • 피드백을 값싸게 더 자주 받을 수 있다.
      • 백도어 접근법: 테스트할 때 어떤 파라미터를 적용하면 내가 원하는 시스템의 시작점으로 가게 하는 것
  • 중복적으로 하는 노력들을 조금 더 자동화하도록 업그레이드하면 발전할 수 있다.

프로그래머 외의 사람들에게 TDD는 어떤 의미가 있을까

프로그래머가 아닌 일반인은 TDD를 어떻게 사용할 수 있을까

  • 마찬가지로 본인이 일을 하면서 내가 하는 일에 대해 나 스스로/다른 사람에게 피드백을 얼마나 자주 받는가를 고민해야 한다.
  • 예를 들어, TDD를 이용하여 ppt(세미나용 발표자료)를 만든다고 하자.
    1. ppt가 충족해야 하는 조건을 정한다. 즉, 핵심 메시지를 정한다.
      • 궁극적으로 발표를 통해서 말하고 싶은 것을 한 단어, 한 문장으로 정한다.
      • “사용자의 피드백”이 중요하다고 정했다.
    2. test1. 단순히 ‘이것이 나한테 중요했다.’가 아닌 ‘어떤 의미에서 중요했는가’가 나타나야 한다.
      • ppt 한 장 이내로 어떤 의미에서 “사용자의 피드백” 중요했는가를 나타나게 한다.
      • 또한 ‘추가적으로 어떤 것을 해볼 수 있을까’를 생각한다.
    3. 실제 test. 만든 것을 실제 발표 상황을 상상하면서 읽어본다. (핵심)
      • 청중 입장에서 어떻게 느껴질까를 생각해본다.
      • 이것이 바로 결정-피드백 사이의 갭의 인식(TDD)을 하는 작업이다.

프로그래머 외의 사람들에게 TDD는 어떤 의미가 있을까

  • TDD는 정형적인 방법으로 하는 것이 중요한 것이 아니라 내가 스스로 TDD라고 하는 방식을 계속해서 발전시켜 나가는 것이 중요하다.
  • 내가 이것을 왜하는가를 생각해야 한다.
  • 피드백과 협력을 증진시키지 않으면서 TDD를 하면 아무 의미가 없다.
  • 그냥 혼자서만 TDD해서 하면 피드백은 되겠지만, 협력이 증진이 되지 않는다.
  • 즉, 정답이 있는것이 아니라 본인이 어떻게 발전시키느냐가 애자일의 핵심이다.

 

출처 :

[Agile] TDD(테스트 주도 개발)란 - Heee's Development Blog (gmlwjd9405.github.io)

'CS' 카테고리의 다른 글

[디자인패턴] MVC, MVP, MVVM 비교  (0) 2021.01.27
프레임워크, 라이브러리, 플러그인 정의  (0) 2021.01.15
CRUD란  (0) 2021.01.12
REST, RESTful  (0) 2021.01.08
DevOps란  (0) 2021.01.08