이 포스트는 기본적인 MVVM 의 지식을 알고 있다는 가정하에 설명되며
개인적인 의견이 많이 포함되어있습니다.
왜 MVVM 을 사용할까요?
저는 개인적으로 3가지 이유를 들수 있습니다.
1. 구체적인 View 를 알지 못하더라도 요구사항에 따라 ViewModel 을 설계할 수 있습니다.
2. ViewModel을 재사용 단위로 설계할 수 있습니다.
3. Testable 합니다.
Github Repositories 를 검색할 수 있는 기획이 있다고 가정해 봅시다.
구체적인 View 를 알지 못하더라도 요구사항에 따라 ViewModel 을 설계할 수 있습니다.
우리는 위에 간단한 Demo 에서 4가지 Case 의 요구사항을 정의할 수 있습니다.
1. Repository는 이름으로 검색할 수 있습니다.
2. 검색을 하면 Loading 이 보여줘야 합니다.
3. 검색된 결과는 Repository Name, Owner Name, Star Count, Fork Count 4가지 항목이 리스트 형태로 보여줘야 합니다.
4. 검색 도중 에러가 발생하면 사용자에서 Alert 를 띄어야 합니다.
우리는 UseCase 에서 Input, Output 의 요소를 뽑아낼 수 있습니다.
Input: Search Field, 검색 버튼
Output: 리스트 형태의 결과, Error Alert
위의 Input Output 의 UseCase 를 바탕으로 View와의 의존성이 없는 ViewModel 을 설계할 수 있습니다.
즉, 구체적인 View를 알지 못하더라도 DataBinding 을 통해 View의 행위를 시킬 수 있습니다.
Client(ViewController) 에서는 ViewModel 상태 변화에 따라 View 를 제어합니다.
View 와의 의존성을 없애기 위한 노력은 개인적으로 이렇게 생각이 듭니다.
1. Test 환경에서 UI Framework 를 의존하는데 많은 비용이 들어갑니다.
iOS 는 UI가 UnitTest 단위로 테스트하는 것이 가능하지만 다른 Android의 경우는 다릅니다.
한번의 테스틑 위해"빌드 > 설치 > 테스트 과정"을 수행하는데 1분 이상 걸린다고 생각해보세요.
개발자 세계에서 시간이 곧 돈이기 때문에 많은 비용이 들어간다는 것은 치명적입니다.
Android TestCode 를 포스트에서는 UI를 테스트 가능하도록 만들기 위하여
* Espresso
* Robolectric
* UIAutomator
UI Testing Framework 를 의존해야만 UI Test 가 가능합니다.
2. UI는 가장 빈번하게 변경이 일어납니다.
아래 그림은 Clean architecture 참고한 것 입니다.
각 UI, Presenter, Use Cases, Entities 의 Layer 가 존재하며 의존성에 방향이 아래로 향하고 있는 것을 알 수 있습니다.
즉, Entities 가 변경되면 Entities 를 의존성하고 있는 상위 Layer 들은 변경이 필요할 수 있다는 것을 의미합니다.
사용자와의 접점인 UI는 가장 상위 Layer 입니다.
상위 Layer 일수록 코드의 변경이 가장 빈번하게 일어날 수 있다는 것이 개인적인 의견입니다.
Testable 합니다.
View와 의존성이 없기 때문에 UnitTest 단위로 View의 행위를 검증할 수 있기도 합니다.
UseCase 2가지에 대해 테스트 코드를 작성할 수 있습니다.
1. Repository는 이름으로 검색할 수 있습니다.
2. 검색을 하면 Loading 이 보여줘야 합니다.
위에 TestCase를 풀어서 설명드리겠습니다.
Given:
search(sortOption:)을 호출하면 성공하는 Mock 객체를 만듭니다.
When:
"test" 검색어를 입력하고 검색 버튼을 누릅니다.
Then:
* isLoading은 true, false 상태가 변화해야합니다.
* service의 search(sortOption:) 은 1번 호출되어야 합니다.
우리는 방금 Presenter Layer 에 대해 TestCase를 작성하였습니다.
Test Code의 전체소스는 여기에서 확인할 수 있습니다.
MVVM 과는 상관없지만 View의 Test Code를 어떻게 작성할 수 있을까요?
View TestCase의 전체소스는 여기에서 확인할 수 있습니다.
View에서 Test Case를 작성하는 예시
UICollectionCell 의 repositoryName text 가 "test" 인지?
UILabel textColor 가 white 인지?
ViewModel을 재사용 단위로 설계할 수 있습니다.
MVVM은 View 1 : N ViewModel 관계를 맺을 수 있습니다.
현재는 Repository 를 검색하는 ViewModel만 존재합니다.
"Code로 검색을 할 수 있다" 라는 요구사항이 추가되었다고 가정해봅시다.
그러면 기존의 ViewModel 의 코드를 변경하는 것이 맞을까요?
만약 기존의 Repository 를 검색하는 로직의 코드까지 변경된다면
ViewModel에 대해 지금까지 진행했던 회귀 테스트는 무효화 될 것 입니다.
즉, 다시 처음부터 테스트를 진행해야 합니다.
SearchCodeViewModel 라는 이름의 ViewModel을 새로 만들고 ViewController에서 사용할 수 있도록 제공하는 것이
코드의 변경을 최소화 할 수 있는 방법입니다.
뿐만 아니라 재사용의 이점이 있습니다.
다른 화면에서 Code를 검색할 수 있는 기능의 요구사항이 있다면 SearchCodeViewModel 만 Binding 시키면 되니까요.
부족하지만 시간내어서 읽어주셔서 감사합니다.
전체코드는 여기에서 확인할 수 있습니다.
소중한 시간 내주셔서 감사합니다
'iOS' 카테고리의 다른 글
[번외편][실전] iOS 사용성 최대로 올려보자! UICollectionView Custom Layout (1) | 2019.09.09 |
---|---|
[번외편][이론] iOS 사용성 최대로 올려보자! UICollectionView Custom Layout (0) | 2019.09.09 |
RxCocoa Binder? ControlEvent? (0) | 2019.09.01 |
iOS 사용성 최대로 올려보자! (Final) - UIViewController Interactive Transition (0) | 2019.08.20 |
iOS 사용성 최대로 올려보자! (Part5) - Easing function (1) | 2019.08.19 |