본문 바로가기
Development Solutions/Flutter & Dart

Description of Flutter's state management library provider for beginners (입문자를 위한 Flutter의 상태관리 라이브러리 Provider 설명)

by studio ODOC 2024. 5. 27.
반응형

입문자를 위한 Flutter의 상태관리 라이브러리 Provider 설명

Description of Flutter's state management library provider for beginners

 

 

Flutter의 상태관리 라이브러리 Provider에 대한 설명



Flutter에서 상태 관리는 중요한 주제 중 하나입니다. 상태 관리란 사용자의 인터페이스와 애플리케이션의 데이터가 일관되도록 유지하는 것을 의미합니다. 다양한 상태 관리 솔루션 중에서 `Provider`는 Flutter 개발자들 사이에서 많이 사용되는 패키지입니다. 이 글에서는 Provider의 기본 개념과 사용 방법, 그리고 예제 프로젝트를 통해 이해를 돕고자 합니다.

 

Provider란 무엇인가?

`Provider`는 상태 관리 및 DI(Dependency Injection) 패턴을 구현한 패키지로, 간단하게 말해 객체의 상태를 관리하고, 이 상태를 여러 위젯에서 쉽게 공유할 수 있도록 도와줍니다. `Provider` 패키지는 Flutter 팀이 추천하는 상태 관리 솔루션 중 하나이며, 사용하기 쉽고 확장성이 뛰어납니다.

 

왜 Provider를 사용하는가?

Flutter는 위젯 트리를 사용하여 UI를 구성합니다. 상태를 관리할 때 흔히 발생하는 문제는 상태를 여러 위젯에 전달해야 하는 경우입니다. 이 경우 상태를 상위 위젯에서 하위 위젯으로 계속 전달하는 것은 비효율적이고 코드가 지저분해질 수 있습니다. `Provider`는 이 문제를 해결하기 위해 설계되었습니다.

 

 

Provider의 주요 개념

1. ChangeNotifier: `Provider`는 주로 `ChangeNotifier`와 함께 사용됩니다. `ChangeNotifier`는 Flutter에서 제공하는 클래스 중 하나로, 변경이 일어날 때 리스너들에게 알리는 기능을 합니다.
2. ChangeNotifierProvider: `ChangeNotifierProvider`는 `ChangeNotifier`를 제공하는 Provider입니다. 위젯 트리에서 `ChangeNotifier`의 인스턴스를 만들고 관리합니다.
3. Consumer: `Consumer` 위젯은 `Provider`를 구독하고, `Provider`에 의해 제공되는 상태가 변경될 때마다 UI를 다시 빌드합니다.
4. Provider.of<T>: `Provider.of<T>` 메서드는 특정 유형의 Provider를 찾고, 이를 통해 제공되는 상태에 접근할 수 있도록 합니다.

 

Provider 사용 예제

이제 간단한 예제 프로젝트를 통해 Provider를 어떻게 사용하는지 살펴보겠습니다. 예제 프로젝트는 간단한 카운터 애플리케이션으로, 사용자가 버튼을 클릭할 때마다 카운트가 증가하는 기능을 구현합니다.

 

1. 프로젝트 생성



먼저 새로운 Flutter 프로젝트를 생성합니다.

#bash

flutter create provider_example
cd provider_example



 

2. dependencies 추가

 


`pubspec.yaml` 파일에 `provider` 패키지를 추가합니다.

#yaml

dependencies:
  flutter:
    sdk: flutter
  provider: ^6.0.3

 

3. 상태 클래스 정의



`lib` 디렉터리에 새로운 파일 `counter.dart`를 생성하고, `ChangeNotifier`를 상속하는 상태 클래스를 정의합니다.

// counter.dart

import 'package:flutter/foundation.dart';

class Counter with ChangeNotifier {
  int _count = 0;

  int get count => _count;

  void increment() {
    _count++;
    notifyListeners();
  }
}



반응형

4. main.dart 수정



`main.dart` 파일을 열고, `ChangeNotifierProvider`를 사용하여 `Counter` 클래스를 위젯 트리에 제공하도록 합니다.

// main.dart

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'counter.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: CounterScreen(),
    );
  }
}

class CounterScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Provider Example'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            Consumer<Counter>(
              builder: (context, counter, child) {
                return Text(
                  '${counter.count}',
                  style: Theme.of(context).textTheme.headline4,
                );
              },
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          Provider.of<Counter>(context, listen: false).increment();
        },
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}

 



코드 설명



1. Counter 클래스: `Counter` 클래스는 `ChangeNotifier`를 상속받아 상태를 관리합니다. `_count` 변수는 현재 카운트 값을 저장하고, `increment` 메서드는 `_count` 값을 증가시키고 `notifyListeners()` 메서드를 호출하여 리스너들에게 변경을 알립니다.

2. main.dart: `ChangeNotifierProvider`를 사용하여 `Counter` 클래스의 인스턴스를 위젯 트리에 제공합니다. `Provider`는 위젯 트리 상에서 상태를 공유할 수 있도록 합니다.

3. Consumer 위젯: `Consumer` 위젯은 `Counter`의 상태를 구독하고, 상태가 변경될 때마다 UI를 다시 빌드합니다. `builder` 메서드는 현재 `Counter` 상태를 받아 UI를 구성합니다.

4. Provider.of: `FloatingActionButton`의 `onPressed` 콜백에서 `Provider.of<Counter>(context, listen: false).increment()`를 호출하여 상태를 업데이트합니다. `listen: false`를 사용하여 이 컨텍스트에서 상태 변경을 리스닝하지 않도록 합니다.

 


추가 기능: 정렬 기능 구현



이제 `ksicCdNm` 필드에 따라 정렬할 수 있는 기능을 추가해보겠습니다. 이를 위해 예제 프로젝트에 `ksicCdNm` 필드를 포함한 데이터를 추가하고, 이를 기준으로 정렬하는 기능을 구현합니다.

 

1. 데이터 모델 수정

`counter.dart` 파일에 추가로 데이터를 저장할 모델 클래스를 정의합니다.

class Item with ChangeNotifier {
  final String ksicCdNm;
  final String name;

  Item({required this.ksicCdNm, required this.name});
}

 

 

2. 상태 클래스 수정

`Counter` 클래스에 아이템 리스트와 정렬 기능을 추가합니다.

class Counter with ChangeNotifier {
  int _count = 0;
  List<Item> _items = [
    Item(ksicCdNm: 'A', name: 'Item 1'),
    Item(ksicCdNm: 'B', name: 'Item 2'),
    Item(ksicCdNm: 'C', name: 'Item 3'),
  ];

  int get count => _count;
  List<Item> get items => _items;

  void increment() {
    _count++;
    notifyListeners();
  }

  void sortItems() {
    _items.sort((a, b) => a.ksicCdNm.compareTo(b.ksicCdNm));
    notifyListeners();
  }
}



 

3. UI 업데이트

`main.dart` 파일을 수정하여 정렬 버튼과 리스트뷰를 추가합니다.

class CounterScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Provider Example'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            Consumer<Counter>(
              builder: (context, counter, child) {
                return Text(
                  '${counter.count}',
                  style: Theme.of(context).textTheme.headline4,
                );
              },
            ),
            ElevatedButton(
              onPressed: () {
                Provider.of<Counter>(context, listen: false).sortItems();
              },
              child: Text('Sort Items by ksicCdNm'),
            ),
            Expanded(
              child: Consumer<Counter>(
                builder: (context, counter, child) {
                  return ListView.builder(
                    itemCount: counter.items.length,
                    itemBuilder: (context, index) {
                      final item = counter.items[index];
                      return ListTile(
                        title: Text(item.name),
                        subtitle: Text(item.ksicCdNm),
                      );
                    },
                  );
                },
              ),
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          Provider.of<Counter>(context, listen: false).increment();
        },
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}



코드 설명

1. Item 클래스: `Item` 클래스는 `ksicCdNm` 필드와 `name` 필드를 포함한 모델 클래스입니다.
2. Counter 클래스 수정: `Counter` 클래스에 `_items` 리스트를 추가하고, 이를 `ksicCdNm` 기준으로 정렬하는 `sortItems` 메서드를 추가했습니다.
3. UI 업데이트: `ElevatedButton`을 추가하여 사용자가 버튼을 클릭할 때 `sortItems` 메서드를 호출하여 리스트를 정렬합니다. `ListView.builder`를 사용하여 정렬된 아이템 리스트를 화면에 표시합니다.


이 예제 프로젝트는 간단하지만, Provider의 기본 개념과 사용 방법을 이해하는 데 도움이 될 것입니다.

Provider를 사용하면 Flutter 애플리케이션에서 상태를 효과적으로 관리하고, 여러 위젯 간에 상태를 쉽게 공유할 수 있습니다.

반응형