MVC 패턴이란?

전통적인 아키텍처 패턴으로 UI를 가지는 앱을 개발하기 위해 앱의 구성 요소를 Model-View-Controller(MVC)로 나누는 방법이다. 하지만, MVC 패턴이 가지는 명확한 한계점 때문에 MVP나 MVVM 패턴에 비해 자주 사용되지는 않는다.

 

MVC에서 View는 데이터를 UI에 보여주는 로직만을 알고 있다. 사용자 입력에 반응하여 View는 Controller에게 입력을 전달하고 Controller는 입력에 알맞은 데이터를 Model에게 요청한다. 데이터가 준비되면 Controller는 View에게 이 사실을 알리고 View는 Model로부터 필요한 데이터를 가져와 UI에 표시해 준다.

 

이러한 흐름은 아래와 같이 표시할 수 있다.

MVC architecture

MVC는 View가 Model의 데이터가 사용 가능 여부를 판단하는 방식에 따라 두 종류로 나뉜다.

  • Passive MVC: Controller가 View에게 Model의 데이터가 갱신되었음을 알림
  • Active MVC: View가 직접 Model의 Observable 데이터를 구독함으로써 데이터 갱신을 처리함

안드로이드에서의 MVC 패턴

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

 

구현을 시작하게 되면 'Activity? Fragment? 어떤 안드로이드 컴포넌트를 View로 사용해야 하지?'라는 고민을 하게 될 수도 있다. View는 UI를 표시하고 유저와 상호작용을 하는 역할을 하므로 Activity, Fragment 모두를 View로써 사용할 수 있다.

View

// 사용자 입력 Controller로 전달
button.setOnClickListener({
    controller.findAddress(editText.text.toString())
})

Controller

fun findAddress(address: String) {
    view.showProgress()
    model.findAddress(address)
}

fun doWhenResultReady() {
    view.hideProgress()
    view.showResult()
}

fun doWhenThereIsErrorFetchingTheResult() {
    view.hideProgress()
    view.showError()
}

Model

fun findAddress(address: String) {
    fetchAddress(address)
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(
            onSuccess = { entityList ->
                list = entityList
                controller.doWhenResultReady()
            },
            onError = {
                controller.doWhenThereIsErrorFetchingTheResult()
            }
        )
        .addTo(disposable)
}

MVC 패턴의 장단점

MVC 패턴을 도입하게 되면 테스트 용이성, 유지 보수성, 확장성이 증가하고 SOLID 원칙 중 단일 책임 원칙을 만족시킬 수 있다는 장점이 있지만 아래와 같은 단점 또한 존재한다.

  1. View가 Controller, Model 모두에 의존적이다.
    UI에 필요한 데이터를 표시하기 위해 View는 Controller에 데이터를 요청해야 하고, 준비 완료된 데이터를 Model로부터 받아와야 한다. 이는 View가 Controller, Model 모두를 알고 있어야 함을 의미한다.
  2. Model의 역할이 너무 광범위하다.
    위의 예시 코드를 보면 Model은 단순 데이터를 만드는 것뿐만 아니라 네트워크 연결, 컨트롤러로의 알림 역할까지 하고 있다. 앱이 비활성화되거나 화면 전환 등이 일어날 경우, Model에서 데이터 요청 작업에 대한 취소 처리까지 해야 함을 의미한다.
  3. View가 UI 로직으로부터 자유롭지 못하다.
    MVC에서는 View가 요청한 결과 데이터를 '어떻게' 보여줄지를 결정한다. View는 UI에 데이터를 보여주고 사용자 입력을 받는 역할만 해야 하는데 '어떻게'에 대한 로직이 포함되므로 좋은 구조라고 할 수 없다. 그렇다고 이 로직을 이미 너무 많은 역할을 하고 있는 Model에 넘길 수도 없다.

결론

MVC 패턴을 사용하면 아키텍처가 없는 것보다 테스트 용이성, 유지보수성, 확장성이 증가하지만 Controller가 View에 표시할 데이터를 직접 전달해 주지 않기 때문에, Controller가 View에 데이터 준비 완료를 알려주면 View가 직접 Model에서 데이터를 읽어와야 하는 구조적 한계점이 있다. 또한, View와 Model이 너무 많은 역할을 맡게 된다는 문제점이 있기 때문에 MVP, MVVM 패턴에 비해 자주 사용되지는 않는다.

+ Recent posts