[flutter] 플러터 앱의 상태 관리 방법

플러터(Flutter)는 구글에서 개발한 크로스 플랫폼 앱 개발 프레임워크로, UI를 손쉽게 구축할 수 있는 강력한 기능을 제공합니다. 하지만 대규모 앱에서는 상태 관리가 중요한 과정이며, 이를 위해 효과적인 상태 관리 방법을 사용해야 합니다.

이 글에서는 플러터 앱에서 상태 관리를 위한 몇 가지 방법을 살펴보겠습니다.

1. 상태 관리 방식 비교

플러터에서는 다양한 상태 관리 방식이 사용될 수 있습니다. 그 중에서도 가장 널리 사용되는 세 가지 방식을 소개합니다.

1.1. 상태를 가진 StatefulWidget

StatefulWidget은 상태를 가지는 위젯입니다. 상태의 변화가 있을 때마다 해당 위젯의 build 메서드가 호출되어 UI가 업데이트됩니다.

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('Count: $_counter'),
        RaisedButton(
          onPressed: _incrementCounter,
          child: Text('Increment'),
        ),
      ],
    );
  }
}

위의 예시에서 _counter 변수는 상태를 나타내며, _incrementCounter() 함수는 상태를 변경하는 메서드입니다. setState()를 통해 상태의 변화를 알려주면 해당 위젯은 다시 그려집니다.

1.2. Provider 패키지 사용하기

Provider 패키지는 플러터에서 가장 많이 사용되는 상태 관리 라이브러리입니다. 상태를 관리하기 위해 ChangeNotifier를 사용하며, 상태의 변화가 있을 때마다 리스너에게 알려줍니다.

class Counter with ChangeNotifier {
  int _count = 0;

  int get count => _count;

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

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

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

위의 예시에서 Counter 클래스는 ChangeNotifier를 상속받아 상태를 관리하고, notifyListeners()를 통해 상태의 변화를 알려줍니다. Provider.of<Counter>(context)를 사용하여 상태에 접근할 수 있습니다.

1.3. BLoC 패턴 사용하기

BLoC(Block Logic Component) 패턴은 플러터에서 상태 관리를 위해 사용되는 또 다른 방법입니다. 이 패턴은 비즈니스 로직을 별도의 컴포넌트로 분리하여 상태를 관리합니다.

class CounterBloc {
  StreamController<int> _counterController = StreamController<int>.broadcast();
  Stream<int> get counter => _counterController.stream;

  int _count = 0;

  void increment() {
    _count++;
    _counterController.sink.add(_count);
  }

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

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

  @override
  Widget build(BuildContext context) {
    return StreamBuilder<int>(
      stream: counterBloc.counter,
      initialData: 0,
      builder: (context, snapshot) {
        return Column(
          children: [
            Text('Count: ${snapshot.data}'),
            RaisedButton(
              onPressed: counterBloc.increment,
              child: Text('Increment'),
            ),
          ],
        );
      },
    );
  }

  @override
  void dispose() {
    super.dispose();
    counterBloc.dispose();
  }
}

위의 예시에서 CounterBloc 클래스는 StreamController를 통해 상태를 관리하며, sink.add()를 통해 상태의 변화를 알려줍니다. StreamBuilder를 사용하여 counterBloc.counter 스트림을 감지하고 UI를 업데이트합니다.

2. 결론

위에서 언급한 상태 관리 방식은 플러터 앱에서 주로 사용되는 방법들입니다. 상황에 따라 적절한 방식을 선택하여 효율적으로 상태를 관리할 수 있습니다. 프로젝트의 규모와 요구 사항에 맞춰서 상태 관리 방식을 선택하는 것이 중요합니다.

더 많은 정보와 예제는 플러터 공식 문서를 참고하시기 바랍니다.

Happy coding! 😊