MVVM을 공부 중이다.
목표는 MVVM-C까지!!
수많은 블로그들이 설명을 잘 써놓아 주셔서 너무 감사하지만, 많은 만큼 의견도 많아서 헷갈린다;;
대략적으로 한 프로젝트에선 아래와 같이 구성되는데, 어떤 라이브러리를 쓸지 AAC 사용할지 등등에 따라 또 다르다.
Kotlin + MVVM + AAC(Databinding, ViewModel, LiveData) + ReactiveX + DI library + Http Library + TDD Library
나는 일단 스터디 프로젝트에 적용할 대상을 찾고 있으므로,
FP개념 + Kotlin + MVVM + AAC(Databinding, ViewModel, LiveData) + RxKotlin + Koin + Retrofit2 + (TDD Lib고민 중)로 구성했다.
(재밌다 완제품을 위한 부품 쇼핑하는 기분이다ㅋㅋ, FP개념은 이번 기회에 더 배워야 할 것 같아 추가했다ㅜㅜ)
그러다 보니, 아래 'TECH CONCERT: ANDROID 2018'에서 Rainist omjoonkim님이 발표한 MVVM이
딱 잘 설명되어 해당 영상을 통해 공부중이다.
- MVVM (from TECH CONCERT: ANDROID 2018)
https://tv.naver.com/v/4635548/list/272653
- 발표 프로젝트 Github (git fork로 가져와서 공부해보는 중이다)
- https://github.com/omjoonkim/GitHubBrowserApp
- 발표하신 프레젠테이션 자료
- https://www.slideshare.net/NaverEngineering/22efficient-and-testable-mvvm-pattern
- 공부 메모_#1 MVVM 개념
MVP와 MVVM의 가장 큰 차이점
- MVP : Presenter가 View에 의존성 가짐
- MVVM : ViewModel이 View에 의존성이 없음
(DataBiding을 통해 Data의 변화를 ViewModel에게 알려주므로) --> [장점] 효율적인 역할과 책임 분배 가능
ViewModel은
- View의 상태(State)와 행동(Behavior)이 추상화된 것.
- 즉, View의 Input(사용자의 행동)과 Output(행동에 같은 결과)이 명시된 인터페이스. -> [장점] (행위적) 테스트에 용이
(이 Input과 Output은 순수함수처럼 같은 Input엔 같은 Output이 나온다.)
Output은 View의 상태와 Route로직으로 나뉜다.
- View의 상태 : View의 상태에 따라 View를 변화시키는 로직
- Route로직 : ex) 다른 Activity로 이동, Dialog show, Toast show 등의 작업 수행
Android UI Controller의 역할
- ViewModel과 View를 Biding하는 역할
- View의 상태변화를 제외한 Router역할
View와 ViewModel은 n:m의 관계
- 하나의 View가 여러 ViewModel에서 사용될 수 있다. (ex?) 레이아웃 XML에서 여러 ViewModel을 databinding해놓고 View에 적용가능)
- 하나의 ViewModel이 여러 View에 적용될 수 있다. (ex?) 서로 다른 View들에서 하나의 ViewModel을 사용가능)
View는 ViewModel에 Bindable하다.
- 사용자의 행동에 의해 Input을 받음 : View ---(DataBinding)-->ViewModel
- 뷰의 상태를 변경시켜야 할 때 또는 어떠한 Route에 대한 액션을 행해야 할 때 : ViewModel---(Notification)-->View
모든 로직 (= 모든 Input에 대한 Output을 산출하는 로직)은 Biding되는 시점에 결정된다! >> [장점] 상태관리 위험성을 줄여줌
[장점] DataBinding, Rx, LiveData 등등과 함께하여 상태를 관리하는 보일러플레이트 코드를 줄일 수 있다.
- 공부 메모_#2 Koin 개념
Koin?
: 제어의 역전(=IoC, Inversion of Control)를 도와주는 라이브러리
- 코틀린 기반의 라이브러리
- IoC를 Service Locator방식으로 구현함 (cf. Dagger는 DI방식으로 구현) -> Dagger보다 진입장벽이 낮고 가벼움
- Android AAC를 지원해준다. (이게 내가 선택한 이유)
- Runtime에서 에러 확인 가능
사용하기
ⓐ build.gradle에 코인 의존성 추가 & Manifest에 Application명시
ⓑ 의존성 명시해놓을 파일에 'myModule'이라는 변수로 의존성 주입할 사항 명시
ⓒ Application에 'startKoin'코드를 추가하여 Application자기자신과 개발자가 만든 의존성 명시 모듈 'myModule'을 start시키도록해줌
- 공부 메모_#3 예제 프로젝트
1. 검색화면
- Input
-
name : 사용자가 검색어를 입력한 값
-
clickSearchButton : 사용자가 검색 요청 시 클릭할 버튼
- Output
- State
-
enableSearchButton : SarchButton의 활성화 상태값. (name입력값의 유무에 따른 Search버튼 활설화 제어
- Route로직
-
goResultActivity : SarchButton 클릭 시 검색결과 화면으로 이동
2. 결과화면
- Input
-
clickHomeButton : back버튼
-
clickUser : 프로필로 이동하는 클릭
- Output
- State
-
title
-
showLoading : 로딩 뷰를 띄울지말지
- Route로직
-
refreshResultData : 리스트의 데이터를 다른 뷰에게 넘겨줌
-
finish : back버튼 클릭 시 종료
-
showErrorToast : 데이터 받기 실패시 에러토스트
-
goProfileActivity : 프로필로 이동
+) 따로 더 공부해야 할 부분
- RxJava Subject
- Koin +) IoC, DI, ServiceLocator
- Clean Architecture
End!
스터디 도움 참조 블로그 (References
- MVVM (from TECH CONCERT: ANDROID 2018) https://tv.naver.com/v/4635548/list/272653 - 발표 프로젝트 Github https://github.com/omjoonkim/GitHubBrowserApp - 발표하신 프레젠테이션 자료 https://www.slideshare.net/NaverEngineering/22efficient-and-testable-mvvm-pattern |