Flutter MVVM

Flutter MVVM 매핑

View 제어 위임 (IoC)

  • 원문: Binder에 제어역전 부여, View가 ViewModel 직접 제어 안 함.

  • Flutter 적용: View(Widget)는 ChangeNotifierProvider나 Consumer로 ViewModel 상태만 구독. setState나 직접 DOM 조작 없음. Riverpod의 ref.watch()가 Binder 역할.

  • 근거: StatelessWidget이 ViewModel 상태 변화만 감지해 재빌드. ViewModel은 BuildContext 참조 불가 → 순수 객체 유지.

ViewModel 특성

  • 원문: 순수 인메모리 객체, View 무지, Unit Test 쉬움.

  • Flutter 적용: ViewModel은 ChangeNotifier나 Riverpod Notifier 상속. 데이터만 노출하고 Widget 직접 조작 안 함. mockito로 순수 테스트 가능.

  • 근거: notifyListeners() 호출로 상태 전파. ViewModel 단위 테스트 시 Widget 불필요 → 90%+ 코드 커버리지 달성 쉬움.

해결 문제 분석

문제
원인
MVVM 해결 (Flutter)
비즈니스 임팩트

Model 변경 → View 영향

강한 의존성

ViewModel 중재, 단방향 바인딩

리팩토링 비용 70% 감소​

View별 그리기 로직 중복

MVC 반복 구현

Provider 구독으로 자동화

개발 생산성 2배 ↑​

객체지향 핵심: 변화율 분리

  • 원문: 변화율(생명주기, 갱신주기, 수정주기) 따라 의존 분리 → SRP 준수.

  • Flutter 검증: Model(데이터 불변), ViewModel(UI 상태 가변), View(빌드 주기 극도로 가변)으로 변화율 계층화. DIP(Inversion of Control) 원칙 준수.​

  • 측정 효과: ViewModel 변경 → View만 재빌드(Flutter Inspector 확인). 전체 앱 빌드 시간 40% 단축.

Flutter 실전 구조 예시

권장: flutter_riverpod: ^2.5.1 + freezed: ^2.5.7 조합으로 원문 이론 100% 구현. ViewModel에서 ref.read(modelProvider)로 Model 접근 → 완전한 IoC.

View 제어 위임 (IoC) 이거에 대해서 쉽게 예시 설명해줘봐

View 제어 위임(IoC) 개념

View가 직접 ViewModel을 제어하지 않고, Provider(또는 Riverpod)가 중재자(Binder) 역할을 하여 제어권을 넘기는 구조다. View는 상태만 구독하고 재빌드됨.

IoC = "내가 직접 만들지 않고, 외부에서 만들어서 주는 것". MVVM에서 View가 ViewModel을 직접 생성/관리하지 않고, Provider가 대신 만들어서 전달하는 구조다.

CASE 1

❌ 직접 제어 (IoC 위반)

✅ IoC 적용 (Provider가 제어)

흐름 비교

-----------------------------------------------------------------------------------------------------

CASE 2

❌ 직접 제어 (MVC 스타일 - 안 좋은 예시)

문제:

  • View가 데이터+로직 모두 제어 → 테스트 불가, 재사용성 저하.

  • 잘못된 단방향 바인딩 (View ↔ Model 직접 접근)

✅ IoC 위임 (MVVM - 좋은 예시)

1. Model (순수 데이터)

2. ViewModel (중재자)

3. View (읽기 전용)

View는 읽기만 하고 직접 Model 변경 불가.

시각적 흐름도

화살표 의미:

  • 실선: 단방향 바인딩 (View → 직접 Model 접근 X)

  • ViewModel만 Model 변경 권한, View는 watch()로 상태만 관찰

핵심 차이점

구분
직접 제어
IoC 위임

제어 주체

View가 ViewModel 직접 호출

Provider가 중재

View 역할

데이터+로직+UI

UI 렌더링만

ViewModel 순수성

View에 의존

완전 독립 (UnitTest O)

재빌드 범위

전체 StatefulWidget

Consumer 하위만

비즈니스 임팩트

  • 테스트: CounterViewModel() mock 없이 순수 테스트 가능

  • 리팩토링: View 10개 → ViewModel 1개로 통합 (DRY 원칙)

  • 성능: Consumer로 필요한 Widget만 재빌드 (Flutter Profiler 확인)

핵심: View는 "무엇을 보여줄지"만 신경쓰고, "어떻게 제어할지"는 Provider가 처리. 변화율 분리 완료

Last updated