글 작성자: HEROHJK

앞에서는 단위테스트를 어떻게 평가해야하는가? 에 대해 알아봤습니다.

 

이번에는 그럼 리팩토링단계로 넘어가서, 어떻게 리팩토링해야 단위테스트를 수월하게 할수 있는지를 알아보겠습니다.

 

1. 아키텍처

1.1 함수형 아키텍처

결정을 내리는 로직 코드와, 결정에 따라 작용하는 코드(주로 입력과 출력)를 나누는 일종의 마이크로서비스 패턴입니다.

1. 가변 셀이 모든 입력을 수집후 코어로 보내고

2. 코어는 입력받은 데이터를 토대로 로직을 수행합니다.

3. 계산된 값들은 다시 가변 셀로나와 사이드이펙트로 변환됩니다.

1.1.1 함수형 프로그래밍?

함수형 아키텍처 이전에, 함수형 프로그램을 먼저 이해하는게 좋습니다.

예전에 제가 Rx Swift에 관한 영상을 제작한적이 있는데요, 도입부를 보다보면 함수형 프로그래밍에 관한 설명이 나옵니다.

필요한 부분만 요약 하자면,

 

1. 함수를 일급 객체로 취급. (= 수학적 순수 함수)

2. 함수가 불변성을 가짐. (전역 상태에 의존하지 않아, 참조 투명성을 가짐)

 

이전에 설명드렸던 출력 기반 테스트와 궤가 같습니다.

 

1.1.3 단점..

기능을 최대한 쪼개어 사용하기 때문에 코드베이스가 커집니다.

따라서 구현시간도 늘어나며, 잘 설계가 되지 않을 때 그만큼 중첩이 되고, 성능에 영향이 갑니다.

그리고 현실적으로, 모든 코드를 함수형 아키텍처로 전환하기는 어렵습니다.

1.2 육각형 아키텍처

이 또한 비즈니스 로직을 중심으로 계층화하는 마이크로서비스 패턴입니다.

구현세부사항 같은 코어 로직과 도메인계층을 분리하는데요,

도메인계층 -> 코어 로직으로 들어갈 때에는 단방향으로 흐릅니다.

외부의 서비스와 통신을 할때에는 도메인계층에서만 통신이 되구요.

 

1.2.1 함수형 아키텍처와 비교?

'입력 -> 처리 -> 출력'이라는 단방향의 흐름은 같습니다.

분리의 경우..

  • 함수형 아키텍쳐는 Core, 즉 메인 로직과 메인 로직이 아닌것을 분리합니다.
  • 육각형 아키텍처는 도메인 계층, 서비스 계층 모두에서 사이드 이펙트를 구분하여 분리합니다. (인터페이스)

2. 리팩토링할 코드 식별하기

자 이제 테스트를 위한 아키텍처도 알아보았으니, 현재 코드를 어떻게 리팩토링해야할까?

즉, 어떻게 고쳐야할까를 생각해봐야 합니다.

일단.. 어떤걸 리팩토링해야하는지 식별하는게 중요합니다.

2.1 코드의 네가지 유형

크게, '복잡도 및 도메인 유의성'과, '협력자 수'를 기준으로 식별하여 분리합니다.

 

해당 코드가 프로젝트에서 개선이 필요한 코드의 도메인과 얼마나 연관이 있는가를 판단합니다. 그것을 도메인 유의성이라고 하며, 그것을 확인하다보면 코드가 정리가 안되 뭉쳐져 있는 경우가 있습니다. 따라서 한꺼번에 복잡도 및 도메인 유의성으로 구분합니다.

 

내부의 의존성을 제외한 가변 의존성과, 외부 의존성의 경우 테스트 비용이 증가합니다.

협력자가 외부 협력자일 경우도 테스트 비용이 증가합니다.

 

도메인 모델과 알고리즘

이부분이 단위테스트에서 테스트할 항목입니다. 적은 비용으로 가장 큰 가치를 얻을 수 있습니다.

 

간단한 코드

기본 생성자, 한줄짜리 속성등 한눈에 이해가 가능한 아주 간단한 코드들입니다. 비용을 생각해서, 특별한 테스트가 필요하지 않습니다.

 

컨트롤러

외부 서비스를 조정하거나, 내부 비즈니스로직들을 조합하여 서비스를 컨트롤하는 부분입니다. 이부분은 단위테스트가 아닌 통합테스트가 필요합니다.

 

지나치게 복잡한 코드

이부분이 리팩토링이 필요한 부분입니다.

예를 들어서 iOS 개발의 ViewController과 같이, 지나치게 Massive한 코드이며, 이 코드를 위 3가지 항목으로 구분하여 최대한 작게 분리하는게 중요합니다.

보통 컨트롤러에서 로직이 포함되면, 이 항목인 지나치게 복잡한 코드가 되기 쉽습니다.

2.2 험블 객체 패턴

지나치게 복잡한 코드는 여러 기능들이 섞여있는데요.

'테스트를 하기 위해 리팩토링'을 하는 관점에서 볼때는 단순하게 '테스트 하기 쉬운 행위', '테스트 하기 어려운 행위'로 나눌수 있겠습니다.

이 때, '테스트 하기 어려운 행위'를 '테스트 하기 쉬운 행위'로 분리하기 위해 로직과 인터페이스들을 단일 책임 원칙에 따라가도록 리팩토링을 하게 되는데요.

이것을 험블 객체 패턴이라고 합니다.

 

아주 간단하게 나누는 방법을 설명하자면..

 

보통 인터페이스와 같이 외부와 연결되는 것들은 테스를 하기가 어렵습니다.

따라서 중요한 로직과 그 외의 것들을 분리합니다.

그러면 위에서 소개한 함수형 아키텍처, 육각형 아키텍처 처럼 모양이 잡힙니다.

아래 그림처럼요

 

앱에서는 이런식으로 구분된 디자인 패턴들이 많죠? MVC, MVP, MVVM등..

그 패턴들도 잘 생각해보면.. 뷰, 모델, 로직을 분리하는데 특화되어있고,

결국은 지나치게 복잡한 코드를 분리하는것으로 귀결됩니다.

 

 

여기까지가 테스트를 수월하게 도입하기 위한 리팩토링 방법 준비에 대한 설명인데요,

다음은 마지막 포스트로, 위의 가이드대로 리팩토링을 한번 진행해보고, 그것을 앞서 말한 평가 방법으로 평가하는 것까지 설명드리겠습니다~

반응형