선생님, 개발을 잘하고 싶어요.

[아키텍쳐] MVVM 정리하기 본문

개발/소프트웨어 개발

[아키텍쳐] MVVM 정리하기

알고싶은 승민 2019. 10. 15. 15:53

도입

  세상에는 많은 아키텍처가 있다. MVC, MVP, MVVM 이 외에도 많은 아키텍처가 존재하고, 이 아키텍처 사이에는 미세한 차이만 있다. 그래서 이런 아키텍처를 어떻게 설명하는지는 사람마다 다를 것이다. 그중에서도 나는 이번 포스트를 통해 내가 MVVM을 어떻게 뭐라고 생각하는지 말할 예정이다.

  

  필자가 최근에 합류한 회사앱은 MVVM을 기반으로 작성이 되어 있다. MVVM을 검색하면 항상 나오는 Data Binding을 적용하지 않았지만, 이게 왜 MVVM인지, 뭐가 부족한지 알아보기 위해 기존의 내 생각을 정리해보자.

 

(참고로 코드 한 줄 없는 MVVM 아이디어에 대한 칼럼이라 지루할 수 있다.)

 

내용

  MVVM은 총 3가지의 컴포넌트로 구성되어 있다. Model, View, ViewModel, 필자는 해당 컴포넌트들이 뭘 모르는지에 집중해서 설명하려고 한다. 무엇을 해야하는지 보다 무엇을 모르는지 이해하는 게 해당 컴포넌트의 역할을 이해하는데 더 도움이 된다고 생각하기 때문이다.

모델 (MODEL)

  필자는 모델(Model)을 MVVM 설명의 시작점으로 잡아보려고 한다. MVC와 MVP에서 말하는 모델과 MVVM의 모델은 다르지 않다. 따라서 가장 범용적이고, 아키텍처들에 공통으로 있는 녀석인 만큼 모델(Model)을 이해하면, 왜 이렇게 많은 패턴들이 생겨났는지 파악하는데 좀 더 쉽게 접근할 수 있을 거라고 생각했다.

  모델은 데이터가 어디서 공급되는지 모른다.

  현실 세계의 데이터는 정말 복잡하다. 또 다양한 데이터 포맷으로 저장된다. 바이너리, json, xml 그리고 단순 text로도 저장된다. 또 다양한 곳에 저장되어 있다. 메모리, 로컬 데이터베이스 그리고 서버 데이터베이스에 저장된다.

 

  하지만 서비스에서 사용하는 본질적인 데이터의 개념은 같다. 어떤 포맷으로 저장되어 있고, 어디에 저장되어 있는가는 프로그램 입장에서 봤을 때 중요하지 않다. 하지만, 프로그래머라면 해당 데이터들을 읽어오는 것을 항상 고민해야한다. 값을 서버에서 얻어오는 방법과 메모리에서 얻어오는 방법은 하늘과 땅 차이로 다르다. 코드 구현도, 신경 써야 할 내용도 모두 다르다.

 

  그러면 우리는 이러한 복잡한 상황에 객체지향의 개념을 적용할 수 있을 것 같다. 위의 복잡한 상황을 처리해주는 마법사 객체(데이터를 공급해주는 마법사)가 있다고 생각하는 것이다. 그리고 모델은 이러한 마법사 객체의 도움을 받는 객체다. 프로그래머는 모델에서 정제된 데이터를 묶고 조합하고 뱉어주면 된다.

    

  데이터를 묶고 조합하는 작업을 좀더 고급지게 표현하면 비즈니스 로직이 되겠다. 우리는 이 모델에서 데이터를 가지고 실제 애플리케이션에서 필요한 기능들을 처리할 수 있다.

 

뷰-모델 (ViewModel)

  뷰-모델(ViewModel)은 이름이 재미있다. View를 그리는데 필요한 Model을 ViewModel이라고 한다.(군더더기 없는 이름이다.) Controller나 Presenter와 같은 View를 직접 조작하는 뉘앙스를 풍기는 이름이 아니라는 것도 신경 써서 볼만하다. ViewModel이라는에서 ViewModel이 View를 직접 다루지 않을 것이라는 스포일러를 하는 셈이다.

뷰-모델은 UI가 그려지는 방법모른다.

  화면은 정말 자주 변경된다. 사용자의 요청에 따라서 디자인이 변경되거나, 화면의 위치가 변경되는 형태이다. 하지만 서비스의 관점에서 봤을때, 기능(feature)은 변하지 않았지만 화면만 변경되는 경우가 있다.

 

  하지만 걱정하지 하라 뷰-모델은 UI가 그려지는 방법을 모른다. 모른다는 건 매우 강한 힘을 가지고 있다. UI가 그려지는 방법을 모르기에, UI를 그리는 방법이 달라져도 뷰-모델를 변경하지 않아도 된다. 

 

  뷰-모델의 구성 요소는 총 3가지라고 볼 수 있다

  1. ViewState (뷰의 상태)
  2. Value Converter (상태의 조합)
  3. Command (뷰의 행동)

  뷰-모델의 구성요소 3가지에 대한 이해가 있으면 필자가 생각하는 MVVM을 이해하는데 도움이 될 것이다.

로그인 화면

ViewState

  뷰의 상태란 화면이 가지는 본질적인 데이터를 의미한다. 위의 화면에서는 아이디, 비밀번호가 뷰의 상태에 해당한다.

 

  뷰-모델에서 뷰의 상태는 뷰에 의해 입력받기도 하고, 뷰 상태에 따라 뷰를 그려주기도 한다. 위의 아이디, 비밀번호의 요소는 EditText를 통해 사용자로부터 뷰-모델에 채워지게 된다.

 

  만약 아이디 저장하기 기능이 있다면, 뷰-모델의 정보가 사용자에게 초기 정보를 보여주는 형태로 구성이 될 수 있겠다.

 

ValueConverter

  상태의 조합은 본질적인 데이터들을 가지고 만들어 내는작업이다. 위에서는 로그인 버튼의 활성화 여부가 상태의 조합에 해당한다고 생각할 수 있는데, 이는 뷰의 상태인 아이디, 비밀번호가 둘다 빈 문자열이 아니여야 하는 조합으로 하나의 불리언 값을 가지게 되고, View에 반영되게 된다.

 

  얼핏보면 ValueConverter도 하나의 ViewState처럼 다룰 수 있다고 생각하기 쉬우나, 이는 애플리케이션의 본질적인 데이터는 아니다. 따라서 ViewState로 무심하게 구성하다가도 ValueConverter로 표현할 수 있는 형식이 아닌지 생각해보자. (ViewState가 적을 수록 가독성이 높아지고, 모듈화 하기 쉽다!)

Command

  View는 사용자에게 정보를 보여주는 창구가 되기도 하지만, 사용자로부터 이벤트를 받아들이는 항구가 되기도 한다. 따라서 뷰-모델은 이러한 일회성 이벤트에도 반응해 줄 수 있어야 한다. 그게 바로 뷰의 행동(Command)다. 이 예시에서는 로그인 동작이 Command가 될것이다. 

 

  뷰의 행동은 항상 ViewState를 활용해 ViewState를 변경하거나, 신호를 내보내는 역할을 한다. (신호를 ViewState의 일종으로 생각해도 좋다.) 따라서 뷰-모델이 노출한 Command는 직접적으로 뷰를 참조하지 않아도 된다.

 

뷰 (View)

  뷰(View)는 추상적인 개념으로는 뷰-모델을 구독하여 소비하는 객체라고 생각하면 된다. 안드로이드 개발에선 하나의 layout 파일이 뷰가 될 수 있겠다. 프로그래머가 개발하는 과정에서 뷰는 상당히 구체적이고 디테일한 영역이기 때문에, 변화에 민감하며 테스트 하기가 어렵다는 특징을 가지고 있다. 따라서 프로그래머는 이러한 뷰를 멍청하게 구성할 필요가 있다.

뷰는 데이터가 어떻게 가공되는지 모른다.

  그래서 뷰는 데이터를 보여주는 창구임에도, 해당 데이터가 어떻게 생성되는지 모른다. 자체적으로 데이터를 생성하지 않는 것을 목표로 한다(테스트가 어려운 객체가 자체적으로 데이터를 만드는 경우, 어떻게 옳은지 검증할 것인가? 빌드 실행 후 손으로 알아볼 것인가?) 

 

  반면 뷰는 사용자의 이벤트를 뷰-모델에게 알려줄 필요도 있다. 이는 보통 뷰-모델의 Command로 사용자 이벤트를 전달하는 형태로 이루어진다.

 

  예시에서 뷰는 당신이 보고 있는 화면 그 자체이고, 실제로 텍스트를 입력할 때, 뷰가 뷰-모델에 데이터를 갱신시켜 줄 것이다. 또한 당신이 로그인 버튼을 누른다면, 뷰-모델에게 간접적으로 로그인 Command를 실행하라고 말해주는 형태인 것이다.

 

결론

  결론적으로 내가 생각하는 MVVM은 

멍청한 View와 정제된 ViewModel 그리고 안정적인 Model을 구성하는 아키텍처 구조

  라고 생각한다. 이런 구조를 만들기 위해서는 ViewModel의 ViewState를 적은 숫자를 유지해야만 한다. 그러기 위해서 Reactive 하게 생각하는 게 필요하다고 생각되는데, Reactive처럼 생각하기 칼럼도 작성할 예정이다. (나도 잘 모른다. 사실 그냥 구구 절절이다.)

Comments