안드로이드/정리

MVVM 패턴과 MVC 패턴의 차이

얼마 전에 이런 질문을 받았어요

UI를 다루는 관점에서 MVC랑 MVVM의 차이가 뭐에요?
MVC에서 Model, View, Controller가 있고 각각 역할이
Model에서 데이터와 비즈니스 로직 관리
View에서 사용자 인터페이스 표시
Controller에서 모델과 뷰 간의 상호 작용을 관리하고 모델 업데이트
로 알고있고
MVVM 에서는 Model, View, ViewModel 3가지고 각각 역할이
Model에서 데이터와 비즈니스 로직 관리
View에서 사용자 인터페이스 표시
ViewModel에서 모델과 뷰 간의 상호 작용 관리하며 프레젠테이션 로직 담당
으로 알고있는데 둘이 같은 것 아니에요 !?

저 또한 위의 질문과 같이 생각을 했었던 적이 있어서

개념을 더 이해하고 실제 구현도 해보며 더욱 이해도를 높이기 위해 이번 포스팅을 작성하게 되었어요

 


 

두 패턴은 Model과 View이 공통적으로 존재해서 서로 유사하다고 생각할 수도 있을거에요

하지만 두 패턴은 ‘데이터 바인딩’이라는 키워드로 극명하게 나뉘어요

MVC 패턴은 데이터와 뷰의 동기화를 수동으로 처리해야하는데, 수동으로 처리한다는 것이 무슨 말이냐면

데이터가 특정 액션을 통해 변경이 일어나면 뷰를 업데이트해야 하는데 이 업데이트하는 과정을 모두 수동으로 해야한다는 것입니다.

 

그리고 업데이트는 뷰가 하는 것일까요? 아니요!

MVC 패턴에서 View의 역할은 사용자의 인터페이스를 표시하는 것이라 Controller가 업데이트를 해주게 됩니다.

 

즉 유저가 어떠한 액션을 했을 때 Controller가 해당 액션을 보고 이것 저것 바쁘게 움직이게 돼요.

 

MVVM 패턴은 어떨까요?

데이터 바인딩을 통해 데이터 모델과 View 사이의 자동 동기화를 제공하고 있어요.

데이터가 변경되면 ViewModel이 이를 감지하고 View를 자동으로 업데이트 됩니다.

유저가 어떠한 액션을 했을 때 View가 ViewModel에게

해당 액션으로 UI가 바뀌어야 한다고 요청하고 ViewModel은 Model에게 데이터를 가져와 View의 화면을 갱신할 수 있도록 처리해요

 

MVC에서 Controller가 View와 Model에 직접적인 의존성을 가질 수 있지만

MVVM에서는 ViewModel이 View에 의존성을 가지고 있지만 View와 Model의 의존성을 분리해 서로의 역할에 충실할 수 있어요

 

이런 차이점이 나중에 어떻게 될까요?

MVC 패턴을 사용한 앱 프로젝트는 View와 Controller사이의 상호 작용이 복잡해질 수 있고 유지 보수가 어려워질 수도 있어요.

하지만 다수의 개발자가 MVC 패턴에 익숙하고 경험이 많기 때문에 빠르게 개발할 수 있죠

단순한 앱이고 복잡한 데이터 바인딩이 필요하지 않다면 MVC 패턴을 고려하여 사용할 가치가 있습니다.

 

하지만 요즘 나오는 앱의 경우엔 복잡한 사용자 인터페이스를 다뤄야하는 경우가 많아

MVVM 패턴이나 다른 디자인 패턴이 더 효과적으로 동작할 수 있다고 생각해요

이해를 돕기 위해 그림으로 설명을 보충해드리자면 !

 

MVC 패턴

유저가 Controller에게 요청을 하면,

Controller는 데이터를 Model에게 받고 View에게 화면을 업데이트 하는 요청을 하게 되는 구조에요~

즉 Controller에서 유저와 상호작용을 하면서 동시에 뷰와 모델과도 지속적으로 상호작용 해야해요..!

Controller가 매우 바빠보이죠…

 

MVVM 패턴

유저가 View에 화면 업데이트 요청을 하면 View는 ViewModel에 요청하고

ViewModel이 Model에게 데이터를 받아 화면을 업데이트할 수 있도록 프레젠테이션 로직을 처리해요~

즉 View에서 유저와 상호작용하고 ViewModel에게 요청하면

ViewModel이 Model에게 데이터를 받아 View의 화면을 업데이트 할 수 있도록 해줘요~

이쪽도 ViewModel이 바쁘긴 하지만 각각의 역할이 분명하기에 괜찮게 느껴집니다.

 


 

자 이제 UI 관점에서 MVC 패턴과 MVVM 패턴의 차이에 대해 알았으니

MVVM으로 구현한 프로젝트를 살펴보면 좋을 것 같아 짧은 시간 진행한 프로젝트로 설명을 드리겠습니다~

 

Android Studio 를 활용해서 Kotlin으로 MVVM 패턴을 구현하였고

https://developer.riotgames.com/ 에서 Riot API를 활용했습니다.

참고 및 사용 자료는 맨 아래에 기입했습니다 😊

 

세팅하는 내용은 생략하겠습니다 😉

만약 전체 소스를 보고싶으신 분은 댓글 주시면 보내드리겠습니다~

 

Model

  • RiotRepository: ViewModel이 요청하는 데이터를 Retrofit을 통해 외부에서 데이터를 가져옴
    • getSummoner: 소환사 이름으로 소환사의 정보에 대해 가져오는 함수

Repository에서 Riot API를 활용해 summonerName으로 소환사의 정보를 가져올 수 있어요~

API를 통해 받은 Response를 ViewModel에게 전달해줍니다. (19, 23 Line)

 

ViewModel

  • MainViewModel: 소환사 정보를 표시할 View인 MainActivity와 상호작용할 ViewModel
    • getSummoner: 소환사 이름으로 해당 소환사의 정보를 가져오는 함수

36번 라인을 확인하면 repository로 부터 소환사의 정보를 받아서

응답이 성공적이면 해당하는 부분(summoner)을 observe하고 있는 View에게 postValue를 통해 데이터의 변경을 알립니다.

 

View

  • MainActivity: 소환사 정보를 표시할 Main View
    • init(): 초기화할 값을 viewModel에게 요청합니다.
    • initObserve(): viewModel을 observe하며 값이 변경이 일어나면 바인딩이 되었기 때문에 자동으로 값을 처리합니다.

37번 Line을 확인하면 viewModel의 summoner를 observe하고 있고 해당하는 값의 변경이 일어나면 프로세스를 수행하여 UI를 갱신합니다.

 

이 프로젝트를 기반으로 MVVM의 원리에 대해 표현하자면

View(MainActivity)에서 사용자가 특정 행동(View에 처음 진입)을 하였고

사용자에게 UI를 보여주기 위해 ViewModel(MainViewModel)에게 필요한 요청을(소환사 정보 가져오기: getSummoner)해요

그리고 UI에 필요한 값을 관리하는 ViewModel을 Observe하여 변경이 있을 때 UI가 조정되는 처리를 합니다.

 

ViewModel(MainViewModel)에서 View로 부터 요청을 받아 원하는 데이터를 Model(RiotRepository)으로부터 요청하고

데이터를 성공적으로 받아오면 View의 화면을 갱신하기 위해 해당 값(소환사 정보: summoner)의 변경을 알려요(postValue)

 

Model(RiotRepository)은 ViewModel로 부터 요청(소환사 정보 가져오기: getSummoner)을 받아

Retrofit을 활용하여 외부 데이터를 API를 통해 가져오고 응답받은 Response를 ViewModel로 다시 전달해요

 

요약

사용자가 앱에 진입 →

View가 소환사의 정보를 사용자에게 보여주기 위해서 ViewModel에 소환사 정보에 대한 데이터 요청 →

ViewModel에서 Model에게 데이터를 요청해서 받아 View가 Observe하는 데이터를 변경 →

View는 ViewModel의 데이터를 관측하다가 데이터가 변경되었을 때를 인식하여 UI를 갱신

 

위 프로세스를 통해 처리된 내용을 첨부하고 마무리하겠습니다~!

 

 

참고&사용 자료

Glide - https://github.com/bumptech/glide

Hilt Dagger - https://developer.android.com/training/dependency-injection/hilt-android?hl=ko

레트로핏 - https://square.github.io/retrofit/

Riot API - https://developer.riotgames.com/