StatefulWidget

하요·2024년 7월 6일
0

Flutter State Management

목록 보기
2/7
post-thumbnail

Flutter에서 간단한 로컬 상태 관리하기: StatefulWidget

StatefulWidget은 Flutter에서 상태를 관리하는 기본적인 방법 중 하나로, 상태가 변할 수 있는 위젯을 만들 때 사용됩니다. StatefulWidget을 통해 동적인 UI 업데이트가 가능하며, 이를 이용해 다양한 상태 기반 인터랙션을 구현할 수 있습니다.

주요 개념

  • StatefulWidget: 상태가 변할 수 있는 위젯을 정의합니다. 상태 변화에 따라 UI를 재구성합니다.
  • State 클래스: StatefulWidget의 상태를 나타내며, 상태 변화를 관리합니다. State 클래스는 StatefulWidget과 분리되어 상태를 독립적으로 관리할 수 있습니다.

주요 속성 및 메서드

  • initState: State 클래스의 초기화 메서드로, 상태 초기화를 수행합니다. State 객체가 처음 생성될 때 한 번 호출됩니다.
  • setState: 상태를 변경하고, UI를 다시 빌드하도록 하는 메서드입니다. 상태가 변경될 때마다 호출합니다.
  • dispose: State 객체가 소멸될 때 호출되는 메서드로, 리소스를 정리하는 데 사용됩니다.

주요 활용도

  • 로컬 상태 관리: 간단한 상태 관리를 할 때 유용합니다. 예를 들어, 버튼 클릭 수 카운트, 입력 필드 값 등.
  • 동적인 UI 업데이트: 상태 변경에 따라 UI를 동적으로 업데이트할 수 있습니다.

코드 예제

아래 예제는 간단한 카운터 앱을 통해 StatefulWidget의 사용 방법을 보여줍니다.

class CounterApp extends StatefulWidget {
  
  _CounterAppState createState() => _CounterAppState();
}

class _CounterAppState extends State<CounterApp> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Counter App')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text('You have pushed the button this many times:'),
            Text('$_counter', style: Theme.of(context).textTheme.headline4),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}

Prop Drilling 문제

StatefulWidget을 사용하여 상태를 관리할 때 발생할 수 있는 문제 중 하나는 Prop Drilling입니다. 이는 부모 위젯에서 자식 위젯으로 상태를 전달할 때 중간에 위치한 모든 위젯이 해당 속성을 전달받아야 하는 문제를 말합니다.

문제점

  • 중간 위젯의 불필요한 속성 전달: 중간 위젯들이 본래 필요하지 않은 속성을 전달받아야 하며, 코드가 복잡해집니다.
  • 코드의 가독성 저하: 각 위젯의 역할이 명확하지 않게 되며, 코드가 길어지고 이해하기 어려워집니다.
  • 유지보수의 어려움: 속성을 전달하는 구조가 변경되면 중간 위젯들의 코드도 함께 수정해야 합니다.

예제

class ParentWidget extends StatefulWidget {
  
  _ParentWidgetState createState() => _ParentWidgetState();
}

class _ParentWidgetState extends State<ParentWidget> {
  String data = "Hello";

  void updateData(String newData) {
    setState(() {
      data = newData;
    });
  }

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Prop Drilling Example')),
      body: MiddleWidget(
        data: data,
        updateData: updateData,
      ),
    );
  }
}

class MiddleWidget extends StatelessWidget {
  final String data;
  final Function(String) updateData;

  MiddleWidget({required this.data, required this.updateData});

  
  Widget build(BuildContext context) {
    return Column(
      children: [
        Text('Middle Widget'),
        ChildWidget(
          data: data,
          updateData: updateData,
        ),
      ],
    );
  }
}

class ChildWidget extends StatelessWidget {
  final String data;
  final Function(String) updateData;

  ChildWidget({required this.data, required this.updateData});

  
  Widget build(BuildContext context) {
    return Column(
      children: [
        Text('Data: $data'),
        ElevatedButton(
          onPressed: () {
            updateData('Hello from Child');
          },
          child: Text('Update Data'),
        ),
      ],
    );
  }
}

Prop Drilling 해결 방법

Prop Drilling 문제를 해결하기 위해 Flutter에서는 다양한 상태 관리 도구를 제공합니다:

  • InheritedWidget: 상위 위젯에서 하위 위젯으로 데이터를 전달할 때 중간 위젯을 거치지 않고 데이터를 전달할 수 있습니다.
  • Provider: Flutter 팀에서 권장하는 상태 관리 도구로, DI(Dependency Injection)와 반응형 상태 관리를 제공합니다.
  • Riverpod: Provider의 개선된 버전으로, 더 안전하고 테스트하기 쉬운 상태 관리를 제공합니다.
  • BLoC (Business Logic Component): 이벤트 기반 상태 관리 패턴으로, 상태의 예측 가능성을 높여줍니다.

추가 팁

  • 성능 최적화: setState는 필요한 경우에만 호출하여 불필요한 위젯 빌드를 최소화해야 합니다.
  • 복잡한 상태 관리: 앱의 상태가 여러 위젯 간에 공유되거나, 글로벌 상태 관리가 필요한 경우, Provider, BLoC, Riverpod와 같은 상태 관리 도구를 사용하는 것이 좋습니다.

관련 자료

추가 참고 리소스

profile
flutter 개발자(진)

0개의 댓글