[Flutter] MVVM TodoList 만들기

2025. 2. 5. 19:20·Flutter/Dart 언어
728x90

📝 Flutter MV 패턴 & MVVM 패턴 정리

Flutter에서 MV (Model-View) 패턴과 MVVM (Model-View-ViewModel) 패턴을 활용하여 코드의 유지보수성과 가독성을 높일 수 있습니다.
이번 포스팅에서는 MV → MVVM으로 발전하는 과정을 코드 예제와 함께 살펴보겠습니다.


1️⃣ MV (Model-View) 패턴 적용

👉 Model과 View만 존재하는 구조
👉 비즈니스 로직이 View에 포함됨 (View와 Model이 강하게 결합됨)


📌 Step 1: Model 생성 (todo_item.dart)

👉 Model은 데이터를 표현하는 역할을 담당

// Model
class TodoItem {
  String title;
  bool isDone;

  TodoItem({required this.title, this.isDone = false});
}

 

📌 역할

  • 데이터 구조를 정의 (title, isDone 속성 포함)
  • 데이터의 상태를 저장 및 변경

📌 Step 2: View 생성 (todo_list_view.dart)

👉 View는 UI 화면을 담당
👉 사용자의 입력을 직접 처리하며, 상태 변경을 담당

import 'package:flutter/material.dart';
import 'package:flutter_statement_v01/_mvvm/_02/models/todo_item.dart';

class TodoListView extends StatefulWidget {
  const TodoListView({super.key});

  @override
  State<TodoListView> createState() => _TodoListViewState();
}

class _TodoListViewState extends State<TodoListView> {
  TextEditingController _controller = TextEditingController();

  // 샘플 데이터
  List<TodoItem> _todoItems = [
    TodoItem(title: '플러터 공부'),
    TodoItem(title: '낮잠 자기', isDone: true),
  ];

  @override
  Widget build(BuildContext context) {
    return Flexible(
      child: Column(
        children: [
          Padding(
            padding: const EdgeInsets.all(16.0),
            child: TextField(
              controller: _controller,
              decoration: InputDecoration(
                hintText: 'Enter todo item...',
                suffixIcon: IconButton(
                  onPressed: () {
                    setState(() {
                      // 새로운 할 일을 추가하는 로직
                      _todoItems.add(TodoItem(title: _controller.text));
                      _controller.clear();
                    });
                  },
                  icon: Icon(Icons.add),
                ),
              ),
            ),
          ),
          SizedBox(height: 16.0),
          Expanded(
            child: ListView.builder(
              itemCount: _todoItems.length,
              itemBuilder: (context, index) {
                final TodoItem item = _todoItems[index];
                return ListTile(
                  title: Text(item.title),
                  trailing: Checkbox(
                    value: item.isDone,
                    onChanged: (value) {
                      setState(() {
                        item.isDone = !item.isDone;
                      });
                    },
                  ),
                );
              },
            ),
          )
        ],
      ),
    );
  }
}

 

📌 문제점

  • setState()를 사용하여 직접 상태를 관리.
  • 비즈니스 로직 (데이터 추가, 체크박스 상태 변경 등)이 View에 포함됨.
  • View가 Model을 직접 조작하여 강한 결합이 발생 → 유지보수 어려움.

2️⃣ MVVM (Model-View-ViewModel) 패턴 적용

👉 ViewModel을 추가하여 View와 Model을 분리
👉 ViewModel에서 비즈니스 로직을 처리하여 View의 역할을 단순화


📌 Step 1: Model (기존과 동일)

// Model
class TodoItem {
  String title;
  bool isDone;

  TodoItem({required this.title, this.isDone = false});
}

 

📌 역할

  • 데이터의 구조 및 상태 유지
  • ViewModel에서 데이터를 관리하도록 지원

📌 Step 2: ViewModel 생성 (todo_list_view_model.dart)

👉 비즈니스 로직을 분리하여 View에서 직접 데이터를 조작하지 않도록 개선

import 'package:flutter_statement_v01/_mvvm/_02/models/todo_item.dart';

class TodoListViewModel {
  List<TodoItem> _items = [];

  // Getter (외부에서 _items 접근 가능)
  List<TodoItem> get items => _items;

  // 비즈니스 로직 - 할 일 추가
  void addItem(String title) {
    _items.add(TodoItem(title: title));
  }

  // 비즈니스 로직 - 완료 상태 변경
  void toggleItem(TodoItem todo) {
    todo.isDone = !todo.isDone;
  }
}

 

📌 개선된 점

  • addItem(), toggleItem()과 같은 비즈니스 로직을 ViewModel에서 관리.
  • View에서 직접 데이터를 조작하지 않고 ViewModel을 통해서만 데이터 변경.

📌 Step 3: View 수정 (todo_list_view.dart)

👉 ViewModel을 사용하여 UI의 역할을 단순화

import 'package:flutter/material.dart';
import 'package:flutter_statement_v01/_mvvm/_02/models/todo_item.dart';
import 'package:flutter_statement_v01/_mvvm/_02/viewmodels/todo_list_view_model.dart';

class TodoListView extends StatefulWidget {
  const TodoListView({super.key});

  @override
  State<TodoListView> createState() => _TodoListViewState();
}

class _TodoListViewState extends State<TodoListView> {
  TextEditingController _controller = TextEditingController();
  final TodoListViewModel _viewModel = TodoListViewModel();

  @override
  Widget build(BuildContext context) {
    return Flexible(
      child: Column(
        children: [
          Padding(
            padding: const EdgeInsets.all(16.0),
            child: TextField(
              controller: _controller,
              decoration: InputDecoration(
                hintText: 'Enter todo item...',
                suffixIcon: IconButton(
                  onPressed: () {
                    setState(() {
                      _viewModel.addItem(_controller.text);
                      _controller.clear();
                    });
                  },
                  icon: Icon(Icons.add),
                ),
              ),
            ),
          ),
          SizedBox(height: 16.0),
          Expanded(
            child: ListView.builder(
              itemCount: _viewModel.items.length,
              itemBuilder: (context, index) {
                final TodoItem item = _viewModel.items[index];
                return ListTile(
                  title: Text(item.title),
                  trailing: Checkbox(
                    value: item.isDone,
                    onChanged: (value) {
                      setState(() {
                        _viewModel.toggleItem(item);
                      });
                    },
                  ),
                );
              },
            ),
          )
        ],
      ),
    );
  }
}

 

📌 개선된 점

  • ViewModel을 사용하여 비즈니스 로직을 View에서 완전히 분리.
  • View는 UI를 렌더링하는 역할만 수행하고, 데이터는 ViewModel에서 관리.
  • 코드의 재사용성과 유지보수성이 향상.

📌 MV → MVVM 패턴 변환 과정 정리

단계 변경 내용 설명
1단계: MV View에서 직접 상태 관리 setState()를 사용하여 직접 Model을 변경
2단계: MVVM ViewModel 추가 ViewModel을 통해 상태를 변경하도록 개선

📝 결론

✅ MVVM 패턴을 사용하면 좋은 점

✔ UI와 비즈니스 로직을 분리하여 유지보수성을 향상할 수 있다.
✔ ViewModel을 활용하여 UI 상태를 관리하여 코드의 가독성을 높일 수 있다.
✔ ViewModel을 활용하면 테스트가 용이해진다.

MVVM을 적용하면 View는 UI만 관리하고, 비즈니스 로직은 ViewModel에서 처리하므로 코드가 더 깔끔하고 유지보수가 쉬워집니다! 🚀

 

MVVM 패턴이란?

 

[Flutter] MVVM 패턴에 대해서 알아 보자

📝 Flutter MVVM 패턴 정리Flutter에서 애플리케이션을 개발할 때, 유지보수성과 확장성을 높이기 위해 MVVM (Model-View-ViewModel) 패턴을 적용할 수 있습니다.이번 포스팅에서는 MVVM 패턴의 개념과 코드

seohong.tistory.com

 

'Flutter > Dart 언어' 카테고리의 다른 글

[Flutter] MVVM + 상태관리  (0) 2025.02.05
[Flutter] MVVM 패턴에 대해서 알아 보자  (0) 2025.02.05
[Flutter] 상태(State)의 종류  (0) 2025.02.03
[Flutter] 상태란 뭘까?  (2) 2025.01.20
Dio 패키지 사용해 보기  (1) 2025.01.14
'Flutter/Dart 언어' 카테고리의 다른 글
  • [Flutter] MVVM + 상태관리
  • [Flutter] MVVM 패턴에 대해서 알아 보자
  • [Flutter] 상태(State)의 종류
  • [Flutter] 상태란 뭘까?
공돌이 출신 개발자
공돌이 출신 개발자
공돌이 출신 개발자입니다
  • 공돌이 출신 개발자
    공돌이 출신 개발자
    공돌이 출신 개발자
  • 전체
    오늘
    어제
    • 분류 전체보기 (124)
      • Database (0)
        • SQL (0)
        • 1일 1쿼리 (9)
      • Flutter (40)
        • Dart 언어 (18)
        • App (22)
      • Git (0)
      • Http 기초 지식 (14)
      • HTML5 & CSS3 (0)
      • Java (33)
      • JSP (0)
      • JavaScript (0)
      • Linux (0)
      • MSA (0)
      • Project (0)
      • React (0)
      • Spring (19)
      • 설치 메뉴얼 (1)
      • [Flutter] 프로젝트 (눈길) (8)
        • 작업일지 (8)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • GitHub
  • 공지사항

  • 인기 글

  • 태그

    로그인
    객체지향
    코딩
    SQL
    안드로이드
    회원가입
    객체
    앱개발
    SQLD
    프로젝트
    프로그래밍
    dart
    jsp
    개발
    안드로이드 앱 개발
    spring boot
    1일1쿼리
    앱 개발
    플러터
    android studio
    Java
    데이터
    클래스
    메서드
    Android
    블로그 만들기
    JAVA 기초
    flutter
    공부
    HTTP
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.2
공돌이 출신 개발자
[Flutter] MVVM TodoList 만들기
상단으로

티스토리툴바