[Flutter] MVVM 디자인 패턴

hodu·2023년 4월 10일
0

Flutter

목록 보기
9/30
post-thumbnail

MVVM패턴을 사용하는 이유

MVC패턴에서 한 번 더 파생되어 의존성 부분을 최소화시켜 나오게 되었다.

MVVM패턴이란, Model, View, ViewModel의 줄임말로 하나의 소프트웨어를 최대한 작은 단위로 나누어 마치 Modul화를 형성하듯 테스트가 쉽고 관리하기도 쉬운 구조를 목표로 한 디자인 패턴이다.

MVC패턴에서의 Model과 View간의 의존성 문제를 극복했을 뿐만 아니라, Controller와 View간의 의존성도 최소화할 수 있다는 장점이 있다.


MVVM 패턴 구조

  • Model : 데이터들을 보관, 처리 등을 수행하는 부분.
  • View : 사용자에게 보이고, 상호작용을 수행하는 부분.
  • ViewModel : View를 표현하기 위해 필요한 데이터를 준비하고, 이벤트 발생 시 Model에 이벤트를 전달하여 변화를 적용하는 역할.(View에 대한 어떠한 정보도 가지지 않으며, View에 의존성이 없도록 한다. 오직 View가 알아서 ViewModel에 있는 정보를 확인할 뿐이다.)

장점 : MVVM 모델의 가장 큰 장점은 View로부터 독립적이기 때문에 별도로 ViewModel만을 떼어내 테스트 할 수 있고, 하나의 ViewModel만으로 여러 개의 View에 활용할 수 있다는 장점이 있다.
기존의 MVC 패턴처럼 View를 위한 Controller를 매번 만들 필요가 없으며 그만큼 View가 View만의 역할을 충실하게 임할 수 있도록 도와준다는 장점이 있다.



폴더 구조

  • config : 앱의 전반적인 구성 요소들.
  • core : 앱에서 전역적으로 사용되는 요소들.
  • data : data layer 관련 요소들.
    -> datasource : api 호출 클래스
    -> model : api 결과 데이터 클래스
    -> repository : api 클래스를 주입받아 사용하는 구현체
  • ui : 사용자에게 보여줄 화면, 상호작용하는 viewModel들.
    -> 화면명 폴더 / page, view, view_model 이 한 세트가 되어 구성된다.



MVVM 패턴 예제.

  1. pubspec.yaml에 provider 라이브러리 추가하기.
    https://pub.dev/packages/provider/install
dependencies:
  flutter:
    sdk: flutter


  # The following adds the Cupertino Icons font to your application.
  # Use with the CupertinoIcons class for iOS style icons.
  cupertino_icons: ^1.0.2
  provider: 6.0.5

  1. lib/ui/number/number_view_model.dart에 코드 작성하기.
    표기될 변수와 증가, 감소 등 함수를 작성한다.
import 'package:flutter/material.dart';

class NumberViewModel with ChangeNotifier{
  int _num = 0;

  int get num => _num;

  void incrementNum(){
    _num++;
    notifyListeners();
  }

  void decrementNum(){
    _num--;
    notifyListeners();
  }
}

  1. lib/ui/number/number_view.dart에 코드 작성하기.
    MVVM 패턴은 반응형으로 화면을 업데이트 해주기 때문에 Stateful이 아닌, StatelessWidget을 사용한다.
    버튼은 ui에서 num처럼 변화하는것을 보여주기 때문에, Provider.of를 사용하여 접근한다.
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:statement/mvvm/ui/number/number_view_model.dart';

class NumberView extends StatelessWidget {
  NumberView({Key? key}) : super(key: key);

  late NumberViewModel _numberViewModel;

  
  Widget build(BuildContext context) {
    _numberViewModel = Provider.of<NumberViewModel>(context, listen: false);

    return Scaffold(
      body: SafeArea(
        child: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Consumer<NumberViewModel>(
                  builder: (_, NumberViewModel viewModel, __) {
                return Text(viewModel.num.toString());
              }),
              ElevatedButton(
                  onPressed: () {
                    _numberViewModel.incrementNum();
                  },
                  child: const Text('증가')),
              ElevatedButton(
                  onPressed: () {
                    _numberViewModel.decrementNum();
                  },
                  child: const Text('감소')),
            ],
          ),
        ),
      ),
    );
  }
}

  1. lib/ui/number/number_page.dart에 코드 작성하기.
    provider를 사용하기 때문에 viewModel을 등록해준다.
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:statement/mvc/view/number_view.dart';
import 'package:statement/mvvm/ui/number/number_view_model.dart';

class NumberPage extends StatelessWidget {
  const NumberPage({Key? key}) : super(key: key);

  
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        ChangeNotifierProvider<NumberViewModel>(
            create: (_) => NumberViewModel()),
      ],
      child: const NumberView(),
    );
  }
}

  1. main.dart에 코드 작성하기.
    보여줄 view의 page를 호출한다.
runApp(
    const MaterialApp(
      title: 'Flutter Demo',
      home: NumberPage(),
    ),
 );

결과

증가 버튼을 클릭하면 위, 반응형으로 표기해둔 숫자(num)이 증가 할 것이고, 감소 버튼을 클릭하면 숫자(num)이 감소 할 것이다.




참고 문서 :
https://m.blog.naver.com/lmj_java/222084721535
https://veiz.me/42
https://www.youtube.com/watch?v=wh6jfZJelf0

profile
Flutter developer

0개의 댓글