Flutter-7: Provider 라이브러리활용하기

안녕하세요, Flutter 개발자 여러분! 이번 포스팅에서는 Flutter 앱의 상태 관리를 개선하기 위해 Provider 라이브러리를 도입하는 방법에 대해 자세히 알아보겠습니다. 이전에 만든 To-Do 리스트 앱을 더욱 효율적이고 확장 가능한 구조로 개선해 볼 거예요.

1. 상태 관리의 중요성

먼저, 상태 관리가 왜 중요한지 이해해 봅시다. 앱이 커지고 복잡해질수록, 여러 위젯에서 공유되는 데이터(상태)를 관리하는 것이 어려워집니다. 효과적인 상태 관리는 다음과 같은 이점을 제공합니다:

  • 코드의 가독성과 유지보수성 향상
  • 성능 최적화
  • 버그 발생 가능성 감소
  • 기능 확장의 용이성

2. Provider 패키지 소개

Provider는 Flutter 팀이 추천하는 상태 관리 솔루션 중 하나입니다. 간단하면서도 강력한 이 라이브러리는 다음과 같은 장점이 있습니다:

  • 사용하기 쉽습니다.
  • Flutter의 위젯 트리와 자연스럽게 통합됩니다.
  • 성능이 우수합니다.
  • 테스트하기 쉽습니다.

3. Provider 설치하기

자, 이제 Provider를 우리 프로젝트에 추가해 봅시다.

  1. pubspec.yaml 파일을 엽니다.
  2. dependencies 섹션에 다음 줄을 추가합니다:
dependencies:
  flutter:
    sdk: flutter
  provider: ^6.0.0
  1. 터미널에서 다음 명령어를 실행합니다:
flutter pub get

이렇게 하면 Provider 패키지가 프로젝트에 설치됩니다.

4. 모델 클래스 생성하기

이제 우리 앱의 데이터 모델을 만들어 봅시다. lib 폴더 안에 models 폴더를 만들고, 그 안에 todo_model.dart 파일을 생성합니다.

import 'package:flutter/foundation.dart';

class Todo {
  String id;
  String title;
  bool isCompleted;

  Todo({required this.id, required this.title, this.isCompleted = false});
}

class TodoModel extends ChangeNotifier {
  List<Todo> _todos = [];

  List<Todo> get todos => _todos;

  void addTodo(Todo todo) {
    _todos.add(todo);
    notifyListeners();
  }

  void toggleTodo(String id) {
    final todo = _todos.firstWhere((todo) => todo.id == id);
    todo.isCompleted = !todo.isCompleted;
    notifyListeners();
  }

  void deleteTodo(String id) {
    _todos.removeWhere((todo) => todo.id == id);
    notifyListeners();
  }
}

이 코드에 대해 자세히 설명해 드리겠습니다:

  • Todo 클래스는 각 할 일 항목을 나타냅니다.
  • TodoModel 클래스는 ChangeNotifier를 상속받아 상태 변화를 알릴 수 있게 합니다.
  • _todos는 private 변수로, 모든 할 일 항목을 저장합니다.
  • addTodo, toggleTodo, deleteTodo 메서드는 상태를 변경하고 notifyListeners()를 호출하여 UI에 변경 사항을 알립니다.

5. Provider 설정하기

이제 main.dart 파일을 수정하여 Provider를 설정합니다:

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'models/todo_model.dart';

void main() {
  runApp(
    ChangeNotifierProvider(
      create: (context) => TodoModel(),
      child: MyApp(),
    ),
  );
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Todo App',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: TodoListScreen(),
    );
  }
}

ChangeNotifierProvider를 사용하여 TodoModel을 앱의 최상위 레벨에서 제공합니다. 이렇게 하면 앱의 어느 위젯에서든 이 모델에 접근할 수 있게 됩니다.

6. UI 업데이트하기

이제 TodoListScreen 위젯을 수정하여 Provider를 사용하도록 만들어 봅시다:

class TodoListScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Todo List'),
      ),
      body: Consumer<TodoModel>(
        builder: (context, todoModel, child) {
          return ListView.builder(
            itemCount: todoModel.todos.length,
            itemBuilder: (context, index) {
              final todo = todoModel.todos[index];
              return ListTile(
                title: Text(todo.title),
                leading: Checkbox(
                  value: todo.isCompleted,
                  onChanged: (_) => todoModel.toggleTodo(todo.id),
                ),
                trailing: IconButton(
                  icon: Icon(Icons.delete),
                  onPressed: () => todoModel.deleteTodo(todo.id),
                ),
              );
            },
          );
        },
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () => _addTodo(context),
        child: Icon(Icons.add),
      ),
    );
  }

  void _addTodo(BuildContext context) {
    showDialog(
      context: context,
      builder: (context) {
        String newTodoTitle = '';
        return AlertDialog(
          title: Text('새 할 일 추가'),
          content: TextField(
            onChanged: (value) {
              newTodoTitle = value;
            },
          ),
          actions: <Widget>[
            TextButton(
              child: Text('추가'),
              onPressed: () {
                if (newTodoTitle.isNotEmpty) {
                  Provider.of<TodoModel>(context, listen: false).addTodo(
                    Todo(id: DateTime.now().toString(), title: newTodoTitle),
                  );
                  Navigator.of(context).pop();
                }
              },
            ),
          ],
        );
      },
    );
  }
}

이 코드에 대해 자세히 설명하겠습니다:

  • Consumer<TodoModel>을 사용하여 TodoModel의 변경 사항을 감지하고 UI를 업데이트합니다.
  • ListView.builder를 사용하여 할 일 목록을 효율적으로 표시합니다.
  • ListTile에서 체크박스와 삭제 버튼을 통해 할 일의 상태를 변경하거나 삭제할 수 있습니다.
  • FloatingActionButton을 눌러 새 할 일을 추가할 수 있습니다.

7. 새 할 일 추가 기능 구현하기

_addTodo 메서드는 다음과 같이 동작합니다:

  1. 사용자에게 새 할 일의 제목을 입력받는 대화 상자를 표시합니다.
  2. 사용자가 ‘추가’ 버튼을 누르면, 입력된 제목으로 새 Todo 객체를 생성합니다.
  3. Provider.of<TodoModel>(context, listen: false)를 사용하여 TodoModel의 인스턴스를 가져옵니다.
  4. addTodo 메서드를 호출하여 새 할 일을 추가합니다.

마무리

이렇게 해서 Provider를 사용하여 To-Do 리스트 앱의 상태 관리를 개선해 보았습니다. 이제 앱의 상태가 중앙에서 관리되며, UI는 이 상태의 변화에 따라 자동으로 업데이트됩니다.

이러한 구조는 앱의 확장성을 크게 향상시키며, 새로운 기능을 추가하기 쉽게 만듭니다. 예를 들어, 할 일 항목 편집 기능이나 완료된 항목 필터링 기능 등을 쉽게 추가할 수 있습니다.

다음 포스팅에서는 이 앱에 데이터 지속성을 추가하여, 앱을 종료하고 다시 열어도 데이터가 유지되도록 만들어 보겠습니다.

Flutter와 Provider를 사용한 상태 관리에 대해 더 궁금한 점이 있다면 언제든 댓글로 남겨주세요. 함께 배우고 성장해 나가요!

관련 리소스

관련 포스팅

Flutter 개발-2: 프로젝트 생성 및 구조 파악 – CSAI

Flutter 개발-3: To-Do 리스트 앱 UI 구현하기 – CSAI

Flutter 개발-4: 앱 상태 관리 추가하기 – CSAI

Flutter 개발-5: 로컬 저장소 추가 – CSAI

Flutter 개발-6: 앱 UI 개선 및 기능 확장 – CSAI

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다