MVVM, 테스팅, 학습
#시작하기 전에
이 글은 MVVM 에 대해 학습에 사용했던 자료들의 중요내용들과 작성한 코드를 일부 정리한 글이다.
어느정도 MVVM에 대해 학습한 사람이라면 링크들만 모아 보는 것을 추천!
공부를 시작하는 사람들에게 이 글의 내용이 디딤돌이 될수 있기를 바란다.
브런치의 글은 카피가 안되고 소스코드를 첨부하기에 적절하지 않아 Medium 에 글을 같이 쓰려한다.
Medium의 글링크를 첨부한다.
MVVM에 대한 글을 가장 기본적인 글을 바탕으로 공부하면서 궁금증이 생기면 관련 내용에 대한 여러 글들을 읽었다. 많은글을 읽어야 하는 이유는 웹상에 많은 글들 중에는 잘못된 내용들도 많기 때문이다.
수많은 글이 있지만 자주 확인하고 읽었던 글들의 링크를 정리했다. 꽤 많다 'ㅁ';
잘못된 글들을 왜 골라낼수 있어야 하는가? 에 대한 개인적인 의견
몇몇 함정카드 성격의 글들을 골라내지 못하면 혼란에 빠지게 되고, 각 요소의 역활을 분리하기가 점점 어려워진다. 많은 사람들이 그런 부분을 겪고 MVVM에 대한 부정적인 시각을 가지게 되는걸 보았다.
이를테면, "비지니스 로직은 어디에 있어야하나 뷰모델?" 랄지, 뷰 모델의 본래 역활이나 가치에 집중하지 않고 뷰에 값을 바인딩 하는데에만 집중한다던지 등의 해석이 그렇다.
자칫 잘못하면 이름만 뷰모델이고 뷰컨트롤러의 책임을 일부만 떼어내놓은 모양새가 되기도 한다.
이제 공부를 시작하는 사람들이라면 충분히 많은 글과 코드를 보고 개념을 이해하면 이런 문제를 방지할수 있을 것 같다. ( TODO 샘플 같은 튜토리얼보다는 좀더 어렵더라도 킥스타터 등의 코드를 보는 것이 도움이 된다고 생각한다)
이 브런치에도 MVVM을 언급하고 TableView 와 CollectionView 를 예제를 잘못된 개념으로 작성된 글이있다. 이처럼 나는 잘못해석한 상태에서 많은 코드를 작성했었다. 나와같이 과오를 범하지 않길 바라며 사족을 달아본다.
- MVVM의 기본적인 설명이 담겨있는 wikipedia
- 블로그 시리즈 글이다. 총 9개의 글로 이루어져 있다. (댓글들도 중요)
- 이규원 님의 블로그 글이다.
위 글에서 몇몇 부분을 정리했다.
1. 뷰를 추상화 하는 것이 핵심이다. (뷰 모델은 뷰를 추상화한 것이다.)
2. 뷰 모델은 value converters 를 가질수 있다.
3. 모델은 데이터, 비즈니스 논리, 서비스 클라이언트 등으로 구성된다.
- 위 글에 정리된 링크 3개도 첨부
https://www.objc.io/books/app-architecture/
- iOS 에서 사용되는 여러 아키텍쳐에 대해서 다룬책(유료)
- 비지니스 로직은 어디에 있어야 하나? 에 대한 스레드
위에 링크한 글들은 필요할때마다 반복해서 읽었다. 처음 읽을때와 프로젝트 중간 중간에 다시 읽을때 느낌이 또 달랐다. 글을 읽은뒤 이해한 내용을 정리하고, 코드를 리뷰하고 잘못 디자인한 코드를 수정하는 과정을 반복했다.
https://github.com/kickstarter/ios-oss
- 킥스타터 오픈소스
테스트 코드까지 모두다 확인이 가능하기 때문에 매우 도움이 되었다. 몇가지 특징에 대해 정리했다.
1. 뷰 모델이 input , output protocol 을 나누어 분리하고 테스트 코드는 protocol 을 테스트 하는 형태로 구성되어있다.
2. AppDelegateViewModel 에 presentViewController 시그널을 받도록 되어있고, 여기서 viewController present 를 수행한다.
'
디자인한 내용을 일부 정리했다. 완전히 숙련된 디자인이라고 생각하지 않는다 아직도 많은 공부가 필요하다. 각 요소의 역할을 분리하는데 집중하려 노력했다.
아래의 내용에 대해 코드 일부를 발췌해서 설명하려 한다.
- 모델의 구성
- 뷰모델의 구성
- 뷰모델과 뷰를 바인딩한 내용
- 테스트 코드
(아래 코드는 RxSwift , RxDataSources 를 사용해본적이 없다면, 다소 난해할수 있다. 그리고 DI도)
브런치는 코드보기에 좋지 않아서 gist 에 정리하고 링크를 첨부했다.
환율 정보를 가져오는 네트워킹 모델
환율 정보를 가져오는 네트워킹 모델이다. Moya 를 사용했고 DI 를 위해 Swinject 를 사용했다. Moya 를 사용하면 mock 응답을 만들기 매우 간단하다. (테스트 코드를 짜기 편하다)
위의 네크워킹 모델중 Firebase Database 에서 환율 정보를 가져오는 모델이다.
서버에서 데이터를 가져와서 Firebase DB에 저장하고, 로컬 DB에도 저장한다. 환율 정보를 제공하는 서버의 API 호출 횟수가 한정적이어서 Firebase DB를 보조 수단으로 사용했으며 관련 코드이다.
로컬 DB (realm) 에 환율 정보가 있는지를 먼저 확인하고, 없다면 Firebase DB 를 확인하고, 없다면 API를 호출한다.
Swift 에서 모델의 구현 방법에 대해서는 enum, struct , class, protocol 등 자유롭게 구현해도 된다고 생각한다. (성격에 따라 singletone 이 될수도 있고)
모델과 뷰모델이 어떻게 데이터를 전달하고 뷰모델은 뷰의 상태를 업데이트 하는등, 각각의 요소를 충실히 분리 했는지가 중요하다고 생각한다.
환율 정보를 가지고 테이블을 구성하는 뷰모델
- 뷰 모델의 value converter 부분
모델이 얻어온 환율정보 데이터를 뷰모델에서 테이블(뷰)에 표시하기 위한 데이터 소스로 가공하는 코드이다. (13 line, RxDataSources를 사용했다.)
- 사용자 입력을 처리하는 부분
유저 입력 -> 환율의 선택 ( 4 line selected function )
유저 입력 -> 환율 선택 취소 (7 line cancel function )
환율정보를 테이블 뷰로 보여주는 ViewController에서 ViewModel 데이터 바인딩
- 뷰모델에서 만든 환율 정보 데이터 소스를 테이블 뷰에 바인딩
(bindProperty 는 UITableView의 RxDataSources 를 구성하는데 도움을 주는 객체)
- 유저 액션 전달
테이블 셀의 선택과 취소 버튼을 누르는 등의 유저 액션을 뷰모델에 전달
뷰모델 테스트 코드
뷰모델 테스트 코드를 일부 발췌했다.
- 얻어온 환율 정보를 유효한 데이터 소스로 변환했는지 확인하는 테스트
- 환율을 선택하면 그 값이 저장되는지 확인하는 테스트
해당 뷰가 사용되는 Scene 의 UI 테스트 코드이다.
유저가 엔화를 선택하는 동작을 했을때 UI테스트 코드이다.
MVVM에 대해 학습한 내용과 자료들을 모아봤고, 디자인한 코드를 일부 발췌했다. 작성한 코드들 중 일부만 발췌해서 보기 힘들겠지만 참고할수 있는 자료가 되었으면 좋겠다. 킥스타터의 오픈소스는 꼭 한번 보는 것을 추천.
아직 더 많이 공부가 필요하다. MVVM은 본래의 의미를 이해하고, 이해한대로 디자인 할수 있다면, 이점이 많은 디자인 패턴이라고 생각한다. 앞으로도 많이 공부하면서 새롭게 알게되는 것이 있다면 그 내용을 공유하는 글을 작성하려 한다.
( 개인적인 의견 ) 테스트를 하지 않을 것이라면 ViewModel 사용의미가 많이 퇴색된다고 본다.
마침.
관련글: [MVVM-C 정리]