[flutter] - Flutter에서 상태 관리하기

Flutter는 사용자 인터페이스(UI)를 빌드하기 위한 강력한 프레임워크입니다. 하지만 앱의 상태를 관리하는 것은 중요한 과제일 수 있습니다. 이 글에서는 Flutter에서 상태 관리를 하는 여러 방법에 대해 알아보겠습니다.

1. StatefulWidget 사용하기

StatefulWidget은 상태를 가지고 있는 위젯입니다. 상태의 변화에 따라 UI를 업데이트할 수 있습니다. StatefulWidget은 createState 메서드를 호출하여 State 객체를 만듭니다. State 객체는 상태를 저장하고 관리하는 역할을 합니다.

class MyWidget extends StatefulWidget {
  @override
  _MyWidgetState createState() => _MyWidgetState();
}

class _MyWidgetState extends State<MyWidget> {
  int counter = 0;

  void incrementCounter() {
    setState(() {
      counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Text('Counter: $counter'),
        RaisedButton(
          onPressed: incrementCounter,
          child: Text('Increment'),
        ),
      ],
    );
  }
}

위의 예제에서는 버튼을 누를 때마다 counter 값을 증가시키고, 화면에 출력합니다. setState 메서드를 호출하여 UI를 업데이트하기 위해 상태를 변경합니다.

2. Provider 패키지 사용하기

Flutter에서는 Provider 패키지를 활용하여 상태 관리를 더욱 간편하게 할 수 있습니다. Provider는 상태를 관리하는 Provider와 상태를 사용하는 Consumer로 구성됩니다.

class Counter with ChangeNotifier {
  int _count = 0;

  int get count => _count;

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

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

    return Column(
      children: [
        Text('Counter: ${counter.count}'),
        RaisedButton(
          onPressed: counter.increment,
          child: Text('Increment'),
        ),
      ],
    );
  }
}

위의 예제에서 Counter 클래스는 ChangeNotifier를 상속받아 상태를 관리합니다. increment 메서드를 호출하면 카운터 값을 증가시키고, notifyListeners를 호출하여 UI를 업데이트합니다. Provider.of<Counter>(context)를 통해 상태를 사용할 수 있습니다.

3. BloC 패턴 사용하기

BloC(Business Logic Component) 패턴은 Flutter 앱에서 상태 관리를 위한 아키텍처 패턴입니다. BloC는 로직을 가지고 있는 컴포넌트입니다. 상태와 이벤트에 따라 로직을 실행하고 상태를 수정합니다.

enum CounterEvent { increment, decrement }

class CounterBloc {
  int _counter = 0;
  final _controller = StreamController<int>();

  Stream<int> get counterStream => _controller.stream;

  void mapEventToState(CounterEvent event) {
    if (event == CounterEvent.increment) {
      _counter++;
    } else if (event == CounterEvent.decrement) {
      _counter--;
    }

    _controller.sink.add(_counter);
  }

  void dispose() {
    _controller.close();
  }
}

class MyWidget extends StatelessWidget {
  final bloc = CounterBloc();

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        StreamBuilder<int>(
          stream: bloc.counterStream,
          builder: (context, snapshot) {
            return Text('Counter: ${snapshot.data}');
          },
        ),
        RaisedButton(
          onPressed: () {
            bloc.mapEventToState(CounterEvent.increment);
          },
          child: Text('Increment'),
        ),
        RaisedButton(
          onPressed: () {
            bloc.mapEventToState(CounterEvent.decrement);
          },
          child: Text('Decrement'),
        ),
      ],
    );
  }
}

위의 예제에서 CounterBloc 클래스는 StreamController를 사용하여 카운터 상태를 관리합니다. mapEventToState 메서드를 호출하여 이벤트에 따라 상태를 변경하고 StreamBuilder를 통해 상태를 구독하고 UI를 업데이트합니다.

결론

Flutter에서 상태 관리는 중요한 부분입니다. StatefulWidget, Provider 패키지, BloC 패턴을 활용하여 각각의 상황에 맞게 상태 관리를 할 수 있습니다. 선택한 방법에 따라 앱의 성능과 유지 보수성이 달라질 수 있으니 신중하게 선택하시기 바랍니다.

참고 자료: