MVVM 패턴이란?

MVVM 패턴은 앱의 구성 요소를 Model, View, ViewModel로 나눈 아키텍처를 말한다. View를 비즈니스 로직으로부터 분리시키고, ViewModel에서 디스플레이 로직을 제외한 대부분의 것들을 처리하는 방식으로 관심사를 분리하여 각 계층 간의 의존성을 최소화하는 방법이다.

MVVM, MVP, MVC architecture

MVC, MVP 패턴과 비교했을 때, MVVM은 각 계층간에 양방향 의존이 없는 것을 확인할 수 있다. ViewModel은 View의 존재를 모르고 View와 무관하게 동작하기 때문에 View가 다른 View로 대체되어도 사이드 이펙트가 발생하지 않는다. 마찬가지로 View 또한 ViewModel의 존재를 모르기 때문에 어떤 ViewModel에서든 사용될 수 있다.

안드로이드에서의 MVVM 패턴

아래는 이해를 돕기 위해 EditText에 검색어를 입력하고 Button을 누르면 해당 검색어로 검색한 결과를 출력해주는 안드로이드 앱이 있다고 가정하고 Model, View, ViewModel에서 하는 역할을 간단한 코드로 작성한 결과이다.

 

예시 코드에서는 View와 ViewModel의 중개자 역할로 RxJava의 Observable을 이용했다. ViewModel은 Model로부터 가져온 데이터를 Observable::onNext를 통해 발행하고, View는 해당 Observable을 구독해서 데이터를 처리하게 된다.

View

// 사용자 입력 ViewModel로 전달
button.setOnClickListener({
    showProgress()
    viewModel.findAddress(editText.text.toString())
})
// Observable 구독을 통한 결과 처리
viewModel.resultListObservable.subscribe({
    hideProgress()
    updateList(it)
})

ViewModel

fun findAddress(address: String) {
    model.fetchAddress(address)
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(
            onSuccess = { entityList ->
                resultListObservable.onNext(entityList)
            },
            onError = { e ->
                resultListErrorObservable.onNext(e as HttpException)
            }
        )
        .addTo(disposable)
}

Model

fun fetchAddress(address: String): Single<List<Entity>> {
    return getRetrofit().fetchAddressFromServer(address)
}

MVVM 패턴의 장단점

MVVM 패턴은 MVP 패턴과 비교해 많은 이점을 갖는다. 각 계층의 관심사 분리가 확실해질 뿐만 아니라 유지보수성, 확장성, 테스트 용이성도 뛰어나다. 또한, View-ViewModel, ViewModel-View 사이의 상호 의존이 사라지면서 프로젝트 규모가 커질 경우, MVP보다 작성해야 할 코드의 양이 감소한다. RxJava/Android, Eventbus, LiveData 등을 이용한 Event-driven 방식의 처리에 익숙하다면 앱을 설계, 개발할 때 가장 유리한 구조가 아닐까 싶다.

+ Recent posts