MVVM

View는 최대한 멍청하게, ViewModel은 테스트 가능한 상태 머신처럼, Model은 비즈니스 규칙의 집합체처럼”

MVVM은 “패턴 자체가 목적”이 아니라 “변경 관리·테스트·협업 구조를 위해 쓰는 도구”

언제 쓰면 좋은가?

  • 화면 수가 많고, 상태 복잡도가 높은 서비스(커머스, 물류, 금융 등)

  • 디자이너/웹뷰/네이티브가 섞여 있고, 뷰 레이어 churn이 잦은 조직

  • TDD/단위테스트를 로직 레벨에서 제대로 가져가고 싶은 팀

MVVM의 구조

  • Model: 서버·DB·로컬에 있는 실제 데이터와 비즈니스 로직을 담당하는 레이어. 엔티티, Repository, UseCase 등이 여기에 온다고 보면 된다.

  • View: 화면에 보이는 UI 그 자체. 버튼, 텍스트, 리스트 같은 것들만 신경 쓰고, 비즈니스 로직은 최대한 안 넣는 게 원칙이다.

  • ViewModel: View가 쓸 수 있게 데이터를 가공해서 내놓고, View에서 오는 이벤트를 받아 Model 쪽에 전달하는 중간 레이어.

MVVM의 목적

  • 변경 이유를 분리

    • View는 “UI/디자인 변경” 때문에 바뀌고, Model은 “비즈니스 정책·데이터 구조 변경” 때문에 바뀐다.

    • MVVM은 이 둘이 서로 직접 참조하지 않게 해서, 한쪽 변경이 다른 쪽에 ‘도미노’로 번지는 걸 줄이려는 구조다.

  • 테스트 가능성 확보

    • ViewModel은 UI 프레임워크에 의존하지 않는, 그냥 평범한 객체로 설계하는 것이 이상적이다.

    • 그래서 UI 없이도 단위 테스트로 상태 전이, 비즈니스 흐름을 검증할 수 있다.

데이터 흐름을 한 사이클로 보면

로그인 화면을 예로 들면:

  1. 사용자가 View에서 “로그인 버튼 클릭”

  2. View는 이 이벤트를 ViewModel에 위임 (ex. viewModel.onLoginClicked(id, pw)).

  3. ViewModel은 Model/Repository에 “로그인 시도” 요청을 보냄.

  4. Model이 서버 호출·검증 후 결과를 ViewModel에 반환.

  5. ViewModel은 결과를 uiState 같은 형태로 가공해서 자신의 상태를 갱신.

  6. View는 ViewModel과 바인딩되어 있으므로, uiState 변화에 따라 자동으로 화면을 다시 그림 (성공/실패 메시지, 로딩 인디케이터 등).

핵심은: View는 “상태를 그리기만” 하고, “상태를 만들고 바꾸는 책임”은 전부 ViewModel에 몰아주는 것이다.

MVVM이 강조하는 원칙

  • View ↔ ViewModel 간 결합도 최소화

    • 이상적인 MVVM에서는 ViewModel이 View의 존재를 몰라야 한다. View는 단지 ViewModel의 공개된 상태와 이벤트 메서드만 본다.

  • 상태 기반 UI

    • “이벤트마다 UI 직접 제어”가 아니라, “이벤트 → 상태 변경 → 상태에 따라 UI가 자동으로 변함” 패턴을 강제한다.

    • 그래서 ViewModel 설계를 사실상 상태 머신 설계처럼 가져가는 게 좋다.

  • 데이터 바인딩 활용

    • 전통적인 MVVM은 데이터 바인딩(Observer, Rx, LiveData, StateFlow 등)을 전제로 한다.

    • 바인딩 덕분에 View가 ViewModel 필드를 계속 polling하지 않고, 변경 시에만 반응한다.

Last updated