[flutter] - Flutter에서의 상태 관리 패턴 (예: Provider, Redux)

안녕하세요! Flutter에서 상태 관리는 애플리케이션 개발에서 가장 중요한 요소 중 하나입니다. 상태 관리 패턴을 효율적으로 구현하면 애플리케이션의 코드 구조를 개선하고 유지 보수성을 향상시킬 수 있습니다. 이번에는 Flutter에서 주로 사용되는 두 가지 상태 관리 패턴인 Provider와 Redux에 대해 알아보도록 하겠습니다.

Provider 패턴

Provider 패턴은 단순하면서도 강력한 상태 관리 솔루션으로 알려져 있습니다. 이 패턴은 의존성 주입(Dependency Injection)을 사용하여 상태를 관리하는 방식입니다. Provider 패키지를 사용하면 상위 위젯에서 하위 위젯으로 상태를 전달할 수 있습니다.

Provider 패턴은 가변 상태와 읽기 전용 상태를 효과적으로 관리할 수 있습니다. 가변 상태를 변경하면 해당 상태를 구독하는 모든 위젯이 업데이트 됩니다. 이를 통해 상태를 효율적으로 공유하고 UI 업데이트를 간단히 처리할 수 있습니다.

Provider 패턴은 다양한 방식으로 구현할 수 있습니다. 가장 일반적인 방법은 ChangeNotifierProvider를 사용하는 것입니다. ChangeNotifierProvider는 애플리케이션의 최상위 위젯에서 시작되는 프로바이더를 생성하고, 하위 위젯에서 이를 사용하여 상태를 업데이트합니다.

class Counter with ChangeNotifier {
  int _count = 0;

  int get count => _count;

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

class CounterScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final counter = Provider.of<Counter>(context);

    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text('Count: ${counter.count}'),
            RaisedButton(
              onPressed: () => counter.increment(),
              child: Text('Increment'),
            ),
          ],
        ),
      ),
    );
  }
}

void main() {
  runApp(
    ChangeNotifierProvider(
      create: (_) => Counter(),
      child: MaterialApp(
        home: CounterScreen(),
      ),
    ),
  );
}

위의 예제에서는 Counter 클래스가 가변 상태를 관리합니다. ChangeNotifierProvider를 통해 최상위 위젯에서 프로바이더를 생성하고, CounterScreen 위젯에서 Provider.of 메소드를 사용하여 프로바이더를 가져옵니다. 이렇게 가져온 프로바이더를 사용하여 상태를 업데이트하고 UI를 구성합니다.

Redux 패턴

Redux 패턴은 상태 관리를 위한 더욱 강력하고 구조적인 솔루션입니다. Redux는 애플리케이션의 상태를 하나의 Store로 관리하고, 상태 변경이 일어나면 Reducer를 통해 새로운 상태를 생성하는 방식입니다.

Flutter에서는 redux 패키지를 사용하여 Redux 패턴을 구현할 수 있습니다. Redux의 핵심 요소인 Store, Action, Reducer, Middleware, Selector 등을 사용하여 상태 관리를 진행합니다.

int counterReducer(int state, dynamic action) {
  if (action == Actions.increment) {
    return state + 1;
  } else if (action == Actions.decrement) {
    return state - 1;
  }
  return state;
}

enum Actions {
  increment,
  decrement,
}

void main() {
  final store = Store<int>(counterReducer, initialState: 0);

  runApp(
    StoreProvider<int>(
      store: store,
      child: MaterialApp(
        home: StoreConnector<int, int>(
          converter: (store) => store.state,
          builder: (context, count) {
            return CounterScreen(count);
          },
        ),
      ),
    ),
  );
}

class CounterScreen extends StatelessWidget {
  CounterScreen(this.count);

  final int count;

  @override
  Widget build(BuildContext context) {
    final store = StoreProvider.of<int>(context);

    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text('Count: $count'),
            RaisedButton(
              onPressed: () => store.dispatch(Actions.increment),
              child: Text('Increment'),
            ),
          ],
        ),
      ),
    );
  }
}

위의 예제에서는 counterReducer 함수를 사용하여 상태 변경을 처리합니다. 액션에 따라 상태를 업데이트하고, 새로운 상태를 반환합니다. StoreProvider를 통해 최상위 위젯에서 Store를 생성하고, StoreConnector 위젯을 사용하여 Store의 상태를 가져와 UI를 구성합니다. 상태 변경은 store.dispatch 메소드를 호출하여 처리할 수 있습니다.

결론

Flutter에서 상태 관리는 중요한 측면으로 애플리케이션의 성능과 유연성에 영향을 줄 수 있습니다. Provider와 Redux는 두 가지 인기 있는 상태 관리 패턴으로, 각각의 특징과 사용법을 알아보았습니다. 상태 관리에서 가장 중요한 것은 애플리케이션의 요구사항과 개발 팀의 선호도에 맞는 패턴을 선택하는 것입니다.