2025. 3. 4. 13:38ㆍ같이 공부합시다 - Flutter/Dart & Flutter 기초부터 실전까지
📃 개요
⚠️ Flutter에서 상태(State)를 관리하는 방법을 모르고 개발하면, 앱의 UI가 예상대로 동작하지 않을 수 있습니다.
⚠️ 잘못된 상태 관리는 코드 복잡도를 증가시키고, 유지보수를 어렵게 만듭니다.
📌 Flutter 개발에서 "상태(State)"를 관리하는 것은 필수적인 개념입니다.
📌 Flutter에서 가장 기본적인 상태 관리 방법은 setState()를 활용하는 것입니다.
✅ 상태(State)란? → UI에 영향을 주는 데이터
✅ setState()란? → 상태가 변경될 때 화면을 다시 그려주는 역할
✅ setState()를 사용하면 StatefulWidget에서 UI를 업데이트할 수 있습니다.
✅ 상태 관리는 앱의 동적인 데이터(예: 버튼 클릭, API 호출 결과)를 UI에 반영하는 과정입니다.
✅ Flutter의 다양한 상태 관리 기법(Provider, Riverpod, Bloc 등)의 기초가 setState()입니다.
🔔 주제
🔸 Flutter에서 상태(State)란?
🔸 setState()를 사용하여 UI 업데이트하기
🔸 StatelessWidget vs StatefulWidget 차이
🔸 StatefulWidget에서 상태를 변경하는 방법
🔸 올바른 상태 관리 패턴과 주의할 점
1️⃣ Flutter에서 상태(State)란?
🔸 Flutter 앱의 UI는 상태(State)에 따라 변합니다.
🔸 Flutter에서 상태는 "변경 가능한 데이터"이며, 이 데이터를 효과적으로 관리하는 것이 중요합니다.
🔸 상태(State)는 사용자의 입력, API 데이터, 애니메이션 등으로 인해 변경되는 값을 의미합니다.
🔸 예를 들어, 사용자가 버튼을 눌러 숫자를 증가시키면, 증가된 숫자가 UI에 반영되어야 합니다.
2️⃣ StatelessWidget vs StatefulWidget 차이
📌 Flutter에는 두 가지 기본 위젯이 있습니다.
| 위젯 | 유형 | 특징 예제 |
| StatelessWidget | 상태가 없는 정적인 UI | 텍스트, 아이콘, 버튼 |
| StatefulWidget | 상태가 변경되는 UI | 카운터, 입력 필드, 체크박스 |
📌 StatelessWidget 예제
class MyStatelessWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("StatelessWidget 예제")),
body: Center(child: Text("나는 변경되지 않는 UI입니다.")),
);
}
}
✅ StatelessWidget은 한 번 생성되면 변경되지 않는 UI를 정의할 때 사용
📌 StatefulWidget 예제
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'setState 예제',
home: const 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++; // 상태 변경 후 UI 업데이트
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text("setState 예제")),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text("버튼 클릭 횟수:", style: TextStyle(fontSize: 20)),
Text("$_counter", style: const TextStyle(fontSize: 40, fontWeight: FontWeight.bold)),
const SizedBox(height: 20),
ElevatedButton(
onPressed: _incrementCounter,
child: const Text("숫자 증가"),
),
],
),
),
);
}
}
🔔 코드 설명
🔸 setState()는 StatefulWidget에서 상태가 변경될 때 UI를 업데이트하는 역할을 합니다.
🔸 setState()를 호출하면 build() 메서드가 다시 실행되면서 화면이 새로 그려집니다.
✅ setState()를 호출하면 _counter 값이 변경되고 UI가 다시 그려짐
✅ StatefulWidget을 사용하여 상태가 변경되는 화면을 구현
3️⃣ setState()란?
🔸 Flutter에서 상태를 변경하려면 반드시 setState()를 호출해야 합니다.
🔸 setState()는 UI를 다시 그려(rebuild) 주는 역할을 합니다.
🔸 StatefulWidget에서만 사용할 수 있으며, StatelessWidget에서는 동작하지 않습니다.
📌 setState() 기본 사용법
setState(() {
_counter++;
});
✅ 이 코드가 실행되면 _counter 값이 증가하고, UI가 다시 렌더링됨
4️⃣ setState()를 사용할 때 주의해야 할 점
⚠️ setState()를 남발하면 성능이 저하될 수 있음
🔸 필요한 부분만 다시 그리도록 최소한의 setState() 사용 권장
⚠️ setState()는 StatefulWidget 내부에서만 사용 가능
🔸 상태 관리가 복잡해질 경우 Provider, Riverpod, Bloc 같은 상태 관리 패턴을 활용
📌 setState()를 사용할 때 주의할 점
1. 불필요한 setState() 호출을 피하기
📌 잘못된 예제 (불필요한 setState() 호출)
setState(() {
_counter++;
print("setState() 호출됨");
});
⚠️ setState() 안에서 print()를 실행하는 것은 불필요한 렌더링을 초래할 수 있음
📌 올바른 예제 (setState() 최소화)
void _increment() {
_counter++;
setState(() {}); // 상태 업데이트 최소화
}
🔸 setState()를 최소한으로 호출하여 성능을 유지하는 것이 중요!
2. setState() 내부에서 API 호출 금지
⚠️ setState() 안에서 비동기 작업을 직접 실행하면 앱이 멈출 수 있음
void fetchData() async {
String data = await fetchFromApi();
setState(() {
result = data; // ✅ setState() 내부에서 UI 업데이트만 수행
});
}
5️⃣ StatefulWidget , setState() 가 포함된 기능 예제
📌 할 일 관리 앱 예제
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: "할 일 관리 앱",
theme: ThemeData(
useMaterial3: true,
colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
),
home: TodoListScreen(),
);
}
}
class TodoListScreen extends StatefulWidget {
const TodoListScreen({super.key});
@override
TodoListScreenState createState() => TodoListScreenState();
}
class TodoListScreenState extends State<TodoListScreen> {
final TextEditingController _controller = TextEditingController();
final List<String> _tasks = [];
void _addTask() {
if (_controller.text.isNotEmpty) {
setState(() {
_tasks.add(_controller.text);
_controller.clear();
});
}
}
void _removeTask(int index) {
setState(() {
_tasks.removeAt(index);
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text("할 일 목록")),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
Row(
children: [
Expanded(
child: TextField(
controller: _controller,
decoration: const InputDecoration(
labelText: "새로운 할 일",
border: OutlineInputBorder(),
),
),
),
const SizedBox(width: 10),
ElevatedButton(
onPressed: _addTask,
child: const Text("추가"),
),
],
),
const SizedBox(height: 20),
Expanded(
child: _tasks.isEmpty
? const Center(child: Text("할 일이 없습니다."))
: ListView.builder(
itemCount: _tasks.length,
itemBuilder: (context, index) {
return Card(
child: ListTile(
title: Text(_tasks[index]),
trailing: IconButton(
icon: Icon(Icons.delete, color: Colors.red),
onPressed: () => _removeTask(index),
),
),
);
},
),
),
],
),
),
);
}
}
🔻 예제 코드 테스트

📌 내용 요약
✅ Flutter에서 "상태(State)"는 UI에 영향을 주는 데이터
✅ StatelessWidget은 변경되지 않는 UI, StatefulWidget은 상태가 변하는 UI에 사용
✅ setState()는 상태가 변경될 때 화면을 다시 렌더링하는 역할
✅ setState()를 최소한으로 사용하여 성능을 유지하는 것이 중요
'같이 공부합시다 - Flutter > Dart & Flutter 기초부터 실전까지' 카테고리의 다른 글
| 📌 Day 13: Provider 상태 관리 적용 테스트 (Counter 앱, 다크모드까지) (1) | 2025.03.06 |
|---|---|
| 📌 Day 12: Provider 패턴 적용 (ChangeNotifier, Consumer) (0) | 2025.03.05 |
| 📌 Day 10: Flutter 다양한 버튼 정리 , Buttons ! (3) | 2025.02.28 |
| 📌 Day 9: Flutter 입력 폼 가이드! (TextField, Form, 유효성 검사까지) (4) | 2025.02.27 |
| 📌 Day 8: Dart & Flutter 기초부터 실전까지! Flutter 화면 전환 완벽 가이드! (Navigator.push, pop, (4) | 2025.02.26 |