반응형
setState, ValueNotifier, Provider 기본
1. 왜 상태관리가 중요한가
Flutter는 상태(State) 변화에 따라 UI를 다시 그리는 Declarative UI 프레임워크입니다.
사용자의 입력, API 응답, 타이머 등으로 데이터가 변하면 그 변화가 화면에 즉시 반영되어야 합니다.
하지만 규모가 커질수록 “누가”, “언제”, “어떤 데이터”를 갱신해야 하는지가 복잡해집니다.
그래서 ‘상태관리(State Management)’는 Flutter 개발의 핵심이 됩니다.
2. 상태의 분류
구분예시관리 방법
| Ephemeral (일시적 상태) | TextField 입력, 현재 탭 | setState, ValueNotifier |
| Shared (공유 상태) | 로그인 정보, 카트 목록 | Provider, Riverpod, BLoC |
| Persisted (지속 상태) | DB/캐시/로컬 저장 | Hive, Isar, shared_preferences |
3. setState()
Flutter의 기본 상태관리 방식입니다.
UI 위젯 내에서 setState() 호출 시 해당 위젯이 다시 빌드됩니다.
class CounterPage extends StatefulWidget {
const CounterPage({super.key});
@override
State<CounterPage> createState() => _CounterPageState();
}
class _CounterPageState extends State<CounterPage> {
int count = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Counter')),
body: Center(child: Text('$count')),
floatingActionButton: FloatingActionButton(
onPressed: () => setState(() => count++),
child: const Icon(Icons.add),
),
);
}
}
장점
- 간단하고 빠름
- 러닝커브 없음
단점
- 여러 위젯 간 상태 공유 불가
- 코드 복잡도 증가
4. ValueNotifier / ValueListenableBuilder
ValueNotifier는 가벼운 옵저버 패턴입니다.
간단한 UI 상태나 폼 값에 적합합니다.
final counter = ValueNotifier<int>(0);
class CounterVNPage extends StatelessWidget {
const CounterVNPage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: ValueListenableBuilder<int>(
valueListenable: counter,
builder: (_, value, __) => Text('$value'),
),
),
floatingActionButton: FloatingActionButton(
onPressed: () => counter.value++,
child: const Icon(Icons.add),
),
);
}
}
💡 ValueNotifier는 폼 검증, 스크롤 위치, 단순 필터링 등에 이상적입니다.
5. Provider / ChangeNotifier
Provider는 Flutter에서 가장 널리 쓰이는 상태관리 도구입니다.
ChangeNotifier 모델을 전역으로 주입해 손쉽게 상태를 공유할 수 있습니다.
예시: 장바구니 모델
class CartModel extends ChangeNotifier {
final List<String> _items = [];
List<String> get items => List.unmodifiable(_items);
int get count => _items.length;
void add(String item) {
_items.add(item);
notifyListeners();
}
void remove(String item) {
_items.remove(item);
notifyListeners();
}
}
Provider 등록 및 사용
void main() {
runApp(
ChangeNotifierProvider(
create: (_) => CartModel(),
child: const MyApp(),
),
);
}
class CartButton extends StatelessWidget {
const CartButton({super.key});
@override
Widget build(BuildContext context) {
final count = context.watch<CartModel>().count;
return Stack(children: [
IconButton(onPressed: () {}, icon: const Icon(Icons.shopping_cart)),
if (count > 0)
Positioned(right: 0, child: CircleAvatar(radius: 10, child: Text('$count')))
]);
}
}
장점
- 코드가 간단하고 직관적
- Flutter 공식 문서에서도 적극 추천
단점
- ChangeNotifier의 가변성 문제
- 대형 프로젝트에선 구조적 한계
반응형
'Dev Study > Flutter & Dart' 카테고리의 다른 글
| Flutter 게임 개발 라이브러리 용도별 장단점 (2025 기준) (0) | 2025.11.06 |
|---|---|
| Flutter 클린 아키텍처에 어울리는 상태관리 가이드 (0) | 2025.11.05 |
| Flutter 상태관리 완전 가이드 (Part 3/3) (0) | 2025.11.05 |
| Flutter 상태관리 완전 가이드 (Part 2/3) (0) | 2025.11.05 |
| Flutter 빌드는 되는데 실행할때 오류나는 경우 (0) | 2025.11.04 |
| Dart 상위 위젯과 하위 위젯의 상태값 가져오기 (0) | 2023.11.20 |
| Dart 상속 (0) | 2023.11.17 |
| Dart Class 생성자 (0) | 2023.11.17 |

