Flutter for Beginners

Flutter의 상태 관리 기본 개념 (setState vs. Provider)

Andrew's Akashic Records 2025. 3. 14. 23:17
728x90

Flutter의 상태 관리 기본 개념 (setState vs. Provider)

Flutter에서 UI는 **상태(State)**에 따라 변경됩니다. 상태 관리(State Management)는 어떻게 데이터를 관리하고 UI에 반영할지를 결정하는 중요한 개념입니다.

1. 상태(State)란?

상태(State)란 UI가 변경될 때 필요한 데이터를 의미합니다.
예를 들어, 버튼 클릭 시 카운터가 증가하는 앱을 만든다면, 카운터 값(int counter)이 상태가 됩니다.

  • StatelessWidget → 변하지 않는(정적인) UI
  • StatefulWidget → 사용자 입력이나 이벤트에 따라 변경되는 UI

2. setState() (기본적인 상태 관리 방법)

setState()는 StatefulWidget 내에서 간단한 상태 관리를 할 때 사용됩니다.

예제: 버튼 클릭 시 카운터 증가 (setState 사용)

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: CounterScreen(),
    );
  }
}

class CounterScreen extends StatefulWidget {
  const CounterScreen({super.key});

  @override
  _CounterScreenState createState() => _CounterScreenState();
}

class _CounterScreenState extends State<CounterScreen> {
  int _counter = 0; // 상태 변수

  void _incrementCounter() {
    setState(() {
      _counter++; // 상태 변경
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("setState 상태 관리")),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text("버튼을 누른 횟수:", style: TextStyle(fontSize: 18)),
            Text(
              "$_counter",
              style: TextStyle(fontSize: 30, fontWeight: FontWeight.bold),
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        child: Icon(Icons.add),
      ),
    );
  }
}

예제코드 실행화면

2.1. setState() 작동 방식

  1. _counter 변수를 setState() 내부에서 변경
  2. setState()가 호출되면 해당 위젯이 다시 빌드됨
  3. 새로운 _counter 값이 화면에 반영됨
  • 간단한 상태 변경 시 사용 가능
  • 상태가 여러 화면에서 공유될 경우 비효율적 (다른 위젯에서 값을 변경하기 어려움)

3. Provider (Flutter 공식 추천 상태 관리 방법)

Flutter 공식 문서에서는 규모가 큰 앱에서는 setState()보다 Provider를 사용할 것을 권장합니다.

Provider란?

  • 전역적으로 상태를 관리하는 방법
  • 여러 위젯에서 공통 상태를 쉽게 공유할 수 있음
  • ChangeNotifier를 활용하여 상태 변경 감지

4. Provider 설치 및 설정

1단계: pubspec.yaml 파일 수정

dependencies:
  flutter:
    sdk: flutter
  provider: ^6.0.5

터미널에서 패키지 설치

flutter pub get

5. Provider 사용 예제: 카운터 증가 앱

setState() 없이 Provider를 이용하여 상태를 관리해보겠습니다.

1단계: 상태 클래스 생성 (CounterProvider.dart)

import 'package:flutter/material.dart';

class CounterProvider with ChangeNotifier {
  int _counter = 0;

  int get counter => _counter;

  void increment() {
    _counter++;
    notifyListeners(); // UI 업데이트
  }
}
  • ChangeNotifier를 상속받아 상태 변경 시 notifyListeners() 호출 → UI 자동 업데이트

2단계: main.dart에서 Provider 설정

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'CounterProvider.dart'; // 상태 클래스 import

void main() {
  runApp(
    MultiProvider(
      providers: [
        ChangeNotifierProvider(create: (context) => CounterProvider()),
      ],
      child: MyApp(),
    ),
  );
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: CounterScreen(),
    );
  }
}
  • MultiProvider로 CounterProvider를 감싸서 전역적으로 상태를 공유할 수 있도록 설정

3단계: UI에서 Provider 데이터 가져오기

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

    return Scaffold(
      appBar: AppBar(title: Text("Provider 예제")),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text("버튼을 누른 횟수:", style: TextStyle(fontSize: 18)),
            Text(
              "${counterProvider.counter}",
              style: TextStyle(fontSize: 30, fontWeight: FontWeight.bold),
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: counterProvider.increment, // Provider 상태 변경
        child: Icon(Icons.add),
      ),
    );
  }
}
  • Provider.of<CounterProvider>(context)를 사용하여 counter 값과 increment() 메서드를 UI에서 직접 사용

6. setState() vs. Provider 비교

비교 항목 setState() Provider
사용 범위 단일 위젯 내부에서만 사용 가능 여러 위젯에서 공통 상태 공유 가능
코드 유지보수 상태가 많아지면 복잡해짐 상태와 UI를 분리하여 유지보수 용이
UI 업데이트 방식 setState() 호출 시 해당 위젯만 다시 빌드 notifyListeners() 호출 시 관련 UI 자동 업데이트
성능 최적화 전체 위젯을 다시 빌드 필요한 위젯만 업데이트
추천 사용 사례 작은 규모의 앱 중~대형 앱 (전역 상태 관리 필요)

 

상황 추천 방법
버튼 클릭 시 UI 변경 (단순 상태 변화) setState()
한 화면 내에서만 상태 유지 setState()
여러 화면에서 상태를 공유 Provider
데이터를 글로벌하게 관리 (예: 로그인 정보, 설정값) Provider

요약

setState()

  • StatefulWidget에서 상태를 변경할 때 사용
  • 간단한 UI 변경에 적합
  • 여러 화면에서 상태를 공유하기 어려움

Provider

  • Flutter 공식 추천 상태 관리 방법
  • 여러 화면에서 상태를 쉽게 공유 가능
  • 성능 최적화가 가능하며 유지보수 용이
728x90