[flutter] 플러터(Flutter)에서 상태 관리를 위해 사용되는 패키지는 무엇이 있나요?

Provider

Provider는 가장 간단하고 직관적인 상태 관리 패키지로 알려져 있습니다. 이 패키지는 InheritedWidgetChangeNotifier를 기반으로 동작하며, 의존성 주입(Dependency Injection)을 통해 상태를 공유할 수 있습니다. Provider는 앱의 전역 상태 관리를 위해 널리 사용되지만, 작은 규모의 상태 관리에도 효과적입니다.

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

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
      create: (context) => Counter(),
      child: Scaffold(
        appBar: AppBar(
          title: Text('Flutter Provider Example'),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Text(
                'Count:',
              ),
              Consumer<Counter>(
                builder: (context, counter, child) => Text(
                  '${counter.count}',
                  style: TextStyle(fontSize: 24),
                ),
              ),
              RaisedButton(
                onPressed: () {
                  Provider.of<Counter>(context, listen: false).increment();
                },
                child: Text('Increment'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

class Counter with ChangeNotifier {
  int count = 0;

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

Bloc

Bloc은 Business Logic Component의 약자로, 상태 관리를 위해 사용되는 패키지입니다. Bloc 패턴은 Fluter에서 많은 인기를 얻었으며, 비즈니스 로직과 상태를 관리하기 위해 StreamSink를 사용합니다. Bloc 패키지는 반응형 및 재사용 가능한 코드 작성을 도와줍니다.

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

enum CounterEvent { increment, decrement }

class CounterBloc extends Bloc<CounterEvent, int> {
  CounterBloc() : super(0);

  @override
  Stream<int> mapEventToState(CounterEvent event) async* {
    switch (event) {
      case CounterEvent.increment:
        yield state + 1;
        break;
      case CounterEvent.decrement:
        yield state - 1;
        break;
    }
  }
}

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final counterBloc = BlocProvider.of<CounterBloc>(context);

    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Bloc Example'),
      ),
      body: Center(
        child: BlocBuilder<CounterBloc, int>(
          builder: (context, count) {
            return Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Text(
                  'Count:',
                ),
                Text(
                  '$count',
                  style: TextStyle(fontSize: 24),
                ),
              ],
            );
          },
        ),
      ),
      floatingActionButton: Column(
        mainAxisAlignment: MainAxisAlignment.end,
        children: <Widget>[
          FloatingActionButton(
            onPressed: () {
              counterBloc.add(CounterEvent.increment);
            },
            child: Icon(Icons.add),
          ),
          SizedBox(height: 16),
          FloatingActionButton(
            onPressed: () {
              counterBloc.add(CounterEvent.decrement);
            },
            child: Icon(Icons.remove),
          ),
        ],
      ),
    );
  }
}

Redux

Redux는 상태 관리를 위한 라이브러리로서, 앱의 상태를 효과적으로 관리하기 위해 사용됩니다. Redux 패턴은 Store, Reducer, Action 등으로 구성되며, 상태 변화를 예측 가능하게 만들어줍니다. Redux 패키지는 다양한 앱 규모에 적용할 수 있으며, 복잡한 비즈니스 로직을 다룰 때 특히 유용합니다.

import 'package:flutter/material.dart';
import 'package:flutter_redux/flutter_redux.dart';
import 'package:redux/redux.dart';

// Actions
class IncrementAction {}

class DecrementAction {}

// Reducer
int counterReducer(int state, dynamic action) {
  if (action is IncrementAction) {
    return state + 1;
  } else if (action is DecrementAction) {
    return state - 1;
  }
  return state;
}

class MyHomePage extends StatelessWidget {
  final store = Store<int>(
    counterReducer,
    initialState: 0,
  );

  @override
  Widget build(BuildContext context) {
    return StoreProvider<int>(
      store: store,
      child: Scaffold(
        appBar: AppBar(
          title: Text('Flutter Redux Example'),
        ),
        body: Center(
          child: StoreConnector<int, int>(
            converter: (store) => store.state,
            builder: (context, count) {
              return Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  Text(
                    'Count:',
                  ),
                  Text(
                    '$count',
                    style: TextStyle(fontSize: 24),
                  ),
                ],
              );
            },
          ),
        ),
        floatingActionButton: Column(
          mainAxisAlignment: MainAxisAlignment.end,
          children: <Widget>[
            FloatingActionButton(
              onPressed: () {
                store.dispatch(IncrementAction());
              },
              child: Icon(Icons.add),
            ),
            SizedBox(height: 16),
            FloatingActionButton(
              onPressed: () {
                store.dispatch(DecrementAction());
              },
              child: Icon(Icons.remove),
            ),
          ],
        ),
      ),
    );
  }
}

위에서 소개한 패키지들은 각기 다른 상태 관리 방식을 제공하며, 개발자는 앱의 특징과 요구 사항에 맞게 선택할 수 있습니다. 상태 관리는 앱의 성능과 유지 보수에 큰 영향을 미치므로, 신중하게 고려해야 합니다.

참고 자료