목표
MVVM 패턴에 대해서 더 자세하게 알아보고, 이를 application을 만드는데 어떻게 사용할 수 있는지 확인하여 본다.
사람들이 만들어 놓은 Application을 해석하고 스스로 Application도 만들다 보니, 문득 궁금한 점이 생겼다. 과연 효율적으로 코드를 작성하고 관리하는 방법들은 무엇이 있을까? Flutter라고 하는 프레임워크도 결국 UI를 빌드하는 (즉, 그리는) 행위를 하는 것과 마찬가지 인데, 디자인패턴의 방법들이 있지 않을까라는 생각이 들었다.
이렇게 하여 찾다보니 대표적인 3가지의 디자인 패턴이 있었다.
1. MVP
2. MVC
3. MVVM
여기서 현재 가장 많이 쓰여지고 있는 MVVM에 대해서 더 알아보도록 하겠다.
1. MVVM 이란?
MVVM이라고 하는 것은 모델-뷰-뷰모델 (model-view-viewmodel)의 약자로 그래픽사용자인터페이스(뷰)의 개발을 비즈니스 로직 또는 백엔드 로직이라고 불리는 모델로 부터 분리를 시킴으로써 뷰가 어느 특정한 모델 플랫폼에 속하지 않도록 하는 것이다. 이렇게 함으로써 사용자 인터페이스와 비즈니스 로직을 분리하여 구분한다는 방법인데, 사실 이렇게 말하면 어렵다.
한번 비유를 들어서 설명을 해보자. 우리가 위젯과 클래스를 막 쌓아서 Flutter라는 프레임워크를 통해 Application이라는 특정한 목적을 가진 제품을 만든다. 그럼 이 만드는 행위들을 빵 만들기에 비유를 해보자.
- '모델'이라는 파트는 식재료와 레시피를 준비한다. 그리고 요리를 하는 파트이다.
- '뷰'라고 하는 것은 제과 제빵을 하는 주방의 자리 그리고 도구 혹은 담겨져 나가는 접시등을 말한다. 뭔가 보이는것에 중점을 둔다.
- '뷰모델'이라고 하는 것은 실제 필요한 재료와 도구를 직접 가져오거나 아니면 맛있게 만들어진 빵을 접시에 담아서 서빙을 한다.
이렇게 3가지 파트로 나누어진 주방은 일사분란하게 움직여서 재료를 준비하고 요리를 한다음에 빵을 구매하려는 사람들에게 시의적절하게 빵을 전달한다. 즉, 효율을 극대화 할 수 있는 분업화를 진행하는 것이다. 이렇게 하지 않고 각각의 파트가 업무를 섞어서 하는 경우 업무의 범위 등에서 혼란이 발생하는 바람에 처리 속도가 늦어지게 되거나 흐름이 꼬이게 될 것이다.
자, 그럼 각 파트를 우리에게 친숙하지 않는 언어로 다시 표현하면 다음과 같다.
- '모델' 실제 상태 내용을 표현하는 도메인 모델 참조 혹은 데이터 접근 계층 내용을 참조하는 요소이다. 다시말하면 데이터베이스나 외부 API와 상호작용하고 데이터를 저장하고 업데이트 한다.
- '뷰' 사용자가 화면에서 보는 것들에 대한 외관에 해당한다.
- '뷰 모델' 뷰와 모델의 중간단계 이며, 뷰에서 발생한 이벤트를 처리하여 모델에서 데이터를 가지고 오도록해 뷰에게 제공하는 역할이다. 즉 데이터의 준비 명령 혹은 데이터 변경시 뷰에게 알리는 역할이다.
자 이렇게 된다면 MVVM에서 중간에 위치하고 있는 것은 무엇이 될까? 그렇다 뷰모델이다. 자 이제 도식화를 해보면 (간단하게)
여기서 데이터 바인딩이라고 하는 것은 뷰와 뷰 모델의 연결을 정의하고 있는 데이터 연결 방식을 통해 뷰 모델로 전달한다는 개념인데, 조금 더 쉽게 설명을 하자면 뷰와 뷰모델간의 데이터를 자동으로 동기화 한다고 보면 된다. 즉 뷰모델에서 변경된 데이터를 뷰에 즉시 반영할 수 있다는 것이다. 이를 구현하는 기술이 안드로이드에서는 Android Databinding Library이다. 데이터 바인딩을 사용하면 뷰와 뷰모델간의 결합도를 낮추고 코드 간소화가 가능해 유지보수성과 생산성을 높일 수 있다. 다만, 사용상의 디버깅들은 필요할 수도 있다. 하지만 이를 통해 데이터의 일관성은 업데이트를 통해 유지가 가능하다.
2. MVVM의 장점
MVVM은 GUI를 bsuinessLogic과는 별도로 분리할 수 있는 만큼 장점이 있다.
- 유지보수서성과 확장성: 뷰와 모델을 분리함으로써 애플리케이션의 유지보수성을 높인다.
- 테스트 용이성: 뷰모델이 UI와 비즈니스로직을 분리하였다보니 뷰모델 단위의 테스트가 별도로 가능하다.
- 개발 생산성: 데이터 바인딩 기술이 포함되어 자동 동기화가 가능하다.
- 유연성: 뷰모델이 뷰와 무관하게 설계가 가능하여, UI 플랫폼 상에 재사용이 가능하다.
- 디버깅의 용이성: 구성 요소들의 분리는 디버깅의 용이함을 가져다 준다.
3. MVVM의 단점
하지만 단순 UI를 분리를 위해서 MVVM 자체가 너무 무겁다는 일각의 시선도 있다. 이와 더불어서 단점을 한번 알아보자.
- 학습성: 다른패턴에 비해 복잡하기에 처음 접하는 개발자에게는 학습 기준이 높다.
- 코드의 양: 데이터 바인딩등을 사용시 코드의 양이 증가하기 때문에, 이에 대한 대응이 필요하다.
- 성능: UI와 뷰모델간의 바인딩을 자동처리 하면서 불필요한 호출이 있을 수 있다.
- 유연성의 한계: 뷰모델이 뷰와 무관하게 설계 가능한 것이 강점이나, UI 플랫폼의 종류에 따라서는 유연성의 제한이 발생할 수 있다.
- 복잡성: 뷰와 모델사이 뷰 모델을 추가하게 된다면 Complexity가 증가하여, 해당 코드를 참고하고자 하는 개발자에게는 해석의 어려움이 발생할 수 있다. 즉, 표준화된 틀이 없어 이해의 정도가 다른 사람들에게는 어려울 수 있다.
4. 그래서 MVVM을 쓰라는건가?
UI와 비즈니스 로직을 구분하여 유지보수성, 확장성, 그리고 테스트 용이성을 확실하게 하고싶다면 해당 구조를 추천한다. 예를 들어서 UI를 변경한다고 하였을때 뷰모델과 모델은 변경하지 않고 UI만 변경하면 코드의 가독성과 재사용성을 높일 수 있다는 장점이 있다. 그렇다 보니 요구 사항 변경, 기획 변경 혹은 버그 등에 대해서 코드의 변경이 필요할때, 변경이 용이한 코드를 작성해야하는 것이 개발자의 숙명이다. MVVM 패턴은 이러한 대응에 적극적이지만 최소한의 변경으로 일의 효율성을 높일 수가 있다.
5. MVVM을 사용해서 만들 수 있는 앱은 무엇이 있을까?
예를 들자면 이 3가지 정도가 아닐까 싶다.
- 쇼핑몰 어플리케이션: 상품 정보, 주문 정보, 결제 정보 등의 데이터를 처리하여야 하며, MVVM 패턴은 상품 정보와 주문 정보등 데이터를 처리하는 모델과 UI를 담당하는 뷰를 분리할 수 있으며 이를 연결해주는 뷰 모델을 만들어서 표현할 수 있다.
- 뉴스 리더 어플리케이션: 다양한 뉴스 소스라는 데이터를 다루다 보니 많은 양의 데이터를 다룰 수 있는 모델이 필요하다. 이때 MVVM 아키텍처를 사용한다면 데이터 수집과 처리를 담당하는 모델과 UI를 담당하는 뷰 그리고 이를 연결해주는 뷰모델을 사용하여 구현가능하다.
- 게임 어플케이션: 플레이어의 정보, 게임상태, 점수 등 데이터가 필요한데, 이때도 마찬가지로 MVVM 패턴을 사용하면 각각의 뷰, 모델, 뷰모델등을 적절하게 사용하여 디자인을 할 수 있다.
즉, 개발을 하는 동안에는 UI, 데이터 처리, 데이터 읽기 등을 병렬적으로 처리 할 수 있다보미 디자이너들과는 병렬적으로 함께 일을 할 수 있다. 또한 거대한 데이터를 따로 처리 할 수 있다보니 복잡한 앱을 만드는데 용이하다. 하지만 소형 앱을 사용하게 되면 오버헤드가 되어 버릴 가능성이 높다.
6. MVVM으로 예시 앱 만들어 보기
자, 그럼 예시 앱을 만들어보자. 여기서 물론 코드를 직접하지는 않겠지만 어떠한 형태로 파일을 나누고 관리를 해야하는지 예를 들어서 구조를 작성해보고자 한다. 만들어 볼 것은 뉴스 리더 어플리케이션이다. 그렇다면 파일 트리를 어떻게 생성할 수 있을지 한번 작성해보자.
- lib/
- models/
- article.dart // 기사 모델
- category.dart // 카테고리 모델
- user.dart // 사용자 모델
- views/
- article_view.dart // 기사 화면 뷰
- category_view.dart // 카테고리 화면 뷰
- user_view.dart // 사용자 화면 뷰
- article_detail_view.dart // 기사 상세 화면 뷰
- category_detail_view.dart // 카테고리 상세 화면 뷰
- view_models/
- article_view_model.dart // 기사 뷰 모델
- category_view_model.dart // 카테고리 뷰 모델
- user_view_model.dart // 사용자 뷰 모델
- article_detail_view_model.dart // 기사 상세 뷰 모델
- category_detail_view_model.dart // 카테고리 상세 뷰 모델
- services/
- news_api_client.dart // 뉴스 API 클라이언트
- database_manager.dart // 로컬 데이터베이스 매니저
- utilities/
- constants.dart // 상수 정의
이 파일트리에서 각각의 폴더와 파일의 역할은 다음과 같다.
models: 데이터 모델의 정의
- article.dart: 기사에 대한 모델
- category.dart: 카테고리에 대한 모델
- user.dart: 사용자에 대한 모델
views: 앱의 화면을 구성하는 뷰
- article_view.dart
- category_view.dart
- user_view.dart
그 외 detail 즉 상세 화면이다.
view_models: 뷰에 대한 뷰 모델을 정의
- article_view_model.dart
- category_view_model.dart
- user_view_model.dart
등은 각각 기사, 카테고리, 사용자 뷰 모델을 정의 하고 그 외는 카테고리 상세 뷰 모델을 정의 한다.
services: 데이터 소스를 관리하는 클래스이다.
- news_api.clinent.dart는 뉴스 API 클라이언트
- database_manager.dart는 파일 로컬 데이터 베이스 매니저
utilities: 유틸리티 클래스를 정의 한다.
- constants.dart는 앱의 상수를 정의 하는데, 색상과 글꼴 크기 등이 포함.
이렇게 디자인하면 어떤 폴더가 어떤 영역을 담당하고 있으며 별도의 테스트를 진행할때도 용이한 것을 확인할 수 있다.
MVVM이라는 것 자체는 모델과 뷰모델의 역할 그리고 작동방식을 이해한다는 것이다. 그리고 효율적인 개발방법과 동료 개발자들에게도 쉽게 읽힐 수 있는 개발 디자인을 한다는것과 같다는 생각이 든다. MVVM 모델을 적용하여 개발한 코드들을 읽고 해석하면서 '클린 코드'에 한발 더 다가설 수 있는 이해력을 높이는 것이 중요하다고 깨닫게 되었다. |
참고자료
- microsoft, The Model-View-ViewModel Pattern
- wikipedia, Model-view-viewmodel
'Flutter' 카테고리의 다른 글
[Firebase+provider]Chp1. Chat App 환경 준비 (0) | 2023.05.04 |
---|---|
[이론] MVC, MVP 패턴 + MVVM 패턴과 비교 (0) | 2023.05.02 |
[Android]Firebase-todo (0) | 2023.04.29 |
[Android]Firebase-Signup (0) | 2023.04.27 |
[Android]Firebase-Logout 구현 + 로그인한 사람 표시 (0) | 2023.04.26 |