본문 바로가기
가치관 쌓기/개발 돌아보기

테스트 주도 설계를 실천한다는 것

by simplify-len 2020. 12. 18.

Bob Ross - 출처 나무위키

밥 로스


로스가 대중에게 인상적인 모습을 보인 것 중 하나가, 그림은 형태를 정하고 하나하나 디테일을 정해가면서 그려 나아가는 것이라는 일반인의 고정관념을 깬 것도 한몫 한다. 이미 그린 수풀이 붓으로 몇 번 칠하니 호수가 된다든지 하는 모습은, 그때그때 마음가는 대로 그려 나아가는 것이 낭만적이라는 느낌을 주기도 한데다, 유화를 배우지 않은 일반인 입장에서 보면 신기할 수밖에 없다.
                                                                                                                                                           - 밥 로스에 대한 평가

 우리는 밥 로스라는 사람을 알고 있습니다. 누가봐도 어려운 그림을 "참 쉽죠?(That easy)" 라는 대사로 유명한 밥로스는 그림을 그리는 방식이 특이하다고 합니다. 그림을 그릴 때, 밥 로스는 하얀 캔버스 위에 아주 약간의 덧칠로서 그림 전체의 윤곽을 만들어 완성 시키면서 그 다음 스텝을 이어간다고 합니다. 캔버스에 전체적의 윤곽을 완성시키면 그 다음에 처음으로 돌아와 윤곽만 잡혀있던 부분에 다시한번 덧칠을 시도하면 또 다시 전체 그림의 윤곽을 덧칠하는 작업을 반복한다고 합니다. 그렇게 조금씩 조금씩 덧칠을 하면서 명확하게 보이지 않았던 그림은 점차 그림이 만들어졌다고 합니다.

https://youtu.be/I-ousb8-SD0

테스트 코드도

 TDD에서 말하는 테스트 코드도 밥 로스의 그림 그리는 전략과 크게 다르지 않는다는 사실을 깨달았습니다. 저는 TDD라는 것을 누군가에게 직접적으로 들어본 적도 없고, 어깨넘어 '테스트 코드를 먼저 짜고 그 테스트 코드를 통과시키며 개발하는 방식' 이라는 것만 알고 있었습니다.

 최근 비교적 간단한 도메인을 활용한 프로젝트를 개발하면서 테스트 주도 설계 라는 것을 실천해보고 싶었습니다. 제가 개발했던 내용을 지인에게 공유하고, 지인이 생각하는 TDD스러운 개발을 보면서 마치 제 머리속에서 전구가 '팍!'하고 켜진 것 같은 느낌을 받았습니다.

 

개발을 하면서 제가 했던 프로세스는 다음과 같았습니다.

 

예를 들어, 재고관리시스템을 예시로 들어보겠습니다.
 제품을 등록하는 기능이라고 가정합니다. 해당 제품은 특정 카테고리를 가지고 있으며, 등록된 제품은 창고에 특정 갯수만큼 입고시킬 수 있습니다. 또한 출하도 시킬수 있는 기능도 있습니다.

 

이런 기능 명세서에서 제가 맨 처음 했던 접근은 공략하기 쉬운 도메인에 집중했습니다.

 

1. 가장 먼저, CRUD를 개발하기 비교적 쉬운 부분, 즉 카테고리를 저장하고, 삭제하는 부분부터 접근했습니다. 카테고리의 도메인 클래스를 만들며

2. 그 다음에는, 카테고리의 CRUD 화면을 개발하고 그 다음에 제품이라는 도메인에 접근해 제품과 관련된 기능 명세서 하나하나를 Clear 하듯이 접근했습니다.

위와같은 방식으로 개발이 어느정도 마무리 짓고 나서, 누군가에게 필자가 개발한 부분을 설명하려고 했을 때, 코드를 보여주고 있지만, 처음 코드를 보는 사람들 입장에서는 이게 무슨 코드인지 스토리가 만들어지지 않았습니다. 테스트 코드를 내밀어도 테스트 코드일 뿐 어떤 역할을 하고 있다는 생각이 들지 않았습니다.

 

 이후, 지인 분이 똑같은 도메인을 가지고 약 2시간동안 TDD스러운(?) 방식으로 개발을 시작했습니다. 시작부터 저와는 다른 접근이였습니다. 기능 명세서를 살펴보고, 여기서 핵심 도메인이 무언인지 빠르게 찾아내어 거기서부터 시작했습니다.

1. 상품이라는 도메인에 먼저 접근하여, 테스트 코드에서 부터 빨간색 가득한 Product 클래스를 먼저 만들어 내며, Product 라는 상품이 가지고 있는 역할을 드러내기 위한 행위를 했습니다. 예를 들어 Product 라는 것은 이름과, 카테고리, 가격 이 3개가 중요한 속성이며 이외에는 부가적인 것이다. 라는 식으로 특정 도메인에 대해서 드러내기 위한 행위를 진행했습니다.

2. 상품이라는 핵심 도메인에 카테고리나 노출 순서, 상품의 상태는 보조적인 도메인이기 때문에 지금 당장은 테스트 코드내에서 표현할 이유가 없다고 하셨습니다. 그 다음에 상품이 창고에 입고되고, 출고되는 판매라는 도메인을 또한번 드러내면서 그 다음 개발이 이어졌습니다. Sales 라는 도메인으로 구별가능한 식별자는 상품과 지점ID. 

3. 그렇게 또 Sales 라는 도메인을 빠르게 테스트 코드내에서 완성시켜갔습니다.

 

 제가 개발했던 방식과는 다르게 지인의 개발 방식의 위에서 설명했던 밥 로스와 많이 닮아 있었습니다. 핵심 도메인에 해당되는 부분을 먼저 윤곽을 만들어 개발하여 전체적인 그림을 먼저 완성시킨 뒤에, 서서히 안에 내용을 채워나가는 방식으로 개발이 진행되었습니다.

 

 

 또한, 지인의 개발을 관찰하며 느꼈던 저와는 다른 점은, 테스트 코드를 개발할 때는 결코 흐름이 끊기지 않아야 했습니다. 하나의 테스트 코드 함수의 구현이 완성될 때까지 그 코드에 집중해 Mock, Class 등 다양한 도구를 활용하셨습니다. 그러나 저는 프로덕션 코드의 구현과 다른 테스트 코드를 넘나들며 하나의 테스트 코드에 집중하지 않았던 부분이 있었습니다.


테스트 주도 설계가 말하는 바는

 TDD 라는 것이 의미하는 바가 무엇일까? 고민했습니다. 지인의 개발을 관찰하며 이런 말씀을 해주셨습니다.

"TDD는 사고 방식을 전향하는 것이다. 테스트 코드가 메인코드가 되어야 하고 극단적으로 말하면, 프로덕션 코드는 보조적인 역할이 되어야 한다" 

 이 말을 처음에는 이해하지 못했는데, 직접 개발하는 모습을 관찰하면서 위 말이 어떤지 이해할 수 있었습니다. 제가 TDD를 실천한다고 떠들며 개발했던 방식에는 테스트 코드에 맞쳐가며 개발하는 것이 아니라, 테스트 코드를 만들다가 다시 프로덕션 코드를 짜고 있고, 결국에는 테스트 코드을 망각한 채, 프로덕션 코드만 짜고 있던 제 모습을 보면서도 더욱 위의 말이 와닿았습니다.

 또한 특정 도메인에 접근하는 방식도 달랐습니다. 그 도메인이 가지고 있는 역할을 곱씹어보며 생각하는 힘도 필요하다는 사실을 알았습니다. 저는 주어진 요구명세서만 보고 이 도메인에는 이런이런 속성을 가지겠구나, 라고 생각했습니다. 이는 에릭에반스이 말하는 스마트UI로 가는 지름길로 가는 것입니다.

 테스트 코드는 이 코드를 이해할 수 있는 사용설명서와 같다는 말씀을 들으면서 제 무릅을 쳤습니다. 프로덕션의 코드를 가장먼저 사용하는 클라이언트 이는 테스트 코드이기 때문에 당연히 사용설명서가 되어야 한다는 것입니다.


책에서 말하는 테스트 코드의 가치는

책 "Effective Unit Testing" 에서 

  • 테스트는 실수를 바로잡아준다.
  • 테스트는 실사용에 적합한 설계를 끌어내준다. - 테스트는 분명 코드를 설계하는 한 방식이다.
  • 테스트는 원하는 동작을 명확히 알려주어 군더더기(gold-plating)을 없애준다.
  • 테스트를 품질 보증 수단으로만 인식하는 한 얻을 수 있는 잠재적 가치는 낮은 곡선을 벗어날 수 없다. 사고의 틀을 깨고 테스트를 프로그래밍 도구, 즉 설계 도구로 인식하는 순간 품질 고지를 띄어넘어 설계 고지에 도달하는 길이 열리게 된다.
  • 테스트를 작성해서 얻게 되는 가장 큰 수확은 테스트 자체가 아니다. 작성 과정에서 얻는 깨달음이다.

마무리

나는 지금부터 위에서 느꼈던 점을 다시한번 상기해보면서 지인이 개발했던 방식대로 다시한번 반복해 개발하고자 합니다. 진행하면서 제가 몰랐던 부분을 알 수도 있을테고, 놓친 부분도 이해할 수 있을 것입니다.

 

댓글