[Flutter] 07. 위젯 기초 - StatelessWidget, StatefulWidget
Flutter의 핵심 개념인 위젯(Widget)의 기본 구조와 종류를 배웁니다.
위젯이란?
Flutter에서 화면에 보이는 모든 것은 위젯입니다.
버튼, 텍스트, 이미지, 레이아웃 등 모든 UI 요소가 위젯으로 구성됩니다.
위젯 트리 구조
MaterialApp
└── Scaffold
├── AppBar
│ └── Text('제목')
└── Body
└── Column
├── Text('안녕하세요')
├── Image(...)
└── ElevatedButton(...)
StatelessWidget
상태가 변하지 않는 위젯입니다. 한 번 그려지면 변경되지 않습니다.
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(
home: Scaffold(
appBar: AppBar(title: const Text('첫 번째 앱')),
body: const Center(
child: Text(
'안녕하세요, Flutter!',
style: TextStyle(fontSize: 24),
),
),
),
);
}
}
StatelessWidget 구조
class MyWidget extends StatelessWidget {
// 1. 생성자
const MyWidget({super.key});
// 2. build 메서드 (UI 반환)
@override
Widget build(BuildContext context) {
return 위젯;
}
}
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(
home: const CounterPage(),
);
}
}
class CounterPage extends StatefulWidget {
const CounterPage({super.key});
@override
State<CounterPage> createState() => _CounterPageState();
}
class _CounterPageState extends State<CounterPage> {
int _count = 0; // 상태 변수
void _increment() {
setState(() {
_count++; // setState 안에서 상태 변경
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('카운터')),
body: Center(
child: Text(
'$_count',
style: const TextStyle(fontSize: 48),
),
),
floatingActionButton: FloatingActionButton(
onPressed: _increment,
child: const Icon(Icons.add),
),
);
}
}
StatefulWidget 구조
// 1. Widget 클래스 (불변)
class MyWidget extends StatefulWidget {
const MyWidget({super.key});
@override
State<MyWidget> createState() => _MyWidgetState();
}
// 2. State 클래스 (가변 상태 관리)
class _MyWidgetState extends State<MyWidget> {
// 상태 변수 선언
int value = 0;
// 상태 변경 시 setState() 호출
void updateValue() {
setState(() {
value++;
});
}
@override
Widget build(BuildContext context) {
return 위젯;
}
}
StatelessWidget vs StatefulWidget
| 항목 | StatelessWidget | StatefulWidget |
|---|---|---|
| 상태 변경 | 불가 | 가능 |
| 리빌드 | 부모가 변경될 때만 | setState() 호출 시 |
| 용도 | 고정 UI (아이콘, 텍스트) | 동적 UI (입력, 애니메이션) |
| 성능 | 더 가벼움 | 상태 관리 오버헤드 |
가능하면 StatelessWidget을 사용하고, 상태 변경이 필요할 때만 StatefulWidget을 사용합니다.
위젯 생명주기
StatefulWidget 생명주기
class _MyWidgetState extends State<MyWidget> {
@override
void initState() {
super.initState();
// 위젯 생성 시 1번 호출 (초기화)
print('initState');
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
// 의존성 변경 시 호출
print('didChangeDependencies');
}
@override
Widget build(BuildContext context) {
// UI 빌드 (setState마다 호출)
print('build');
return Container();
}
@override
void didUpdateWidget(MyWidget oldWidget) {
super.didUpdateWidget(oldWidget);
// 부모 위젯이 변경될 때 호출
print('didUpdateWidget');
}
@override
void dispose() {
// 위젯 제거 시 호출 (정리 작업)
print('dispose');
super.dispose();
}
}
생명주기 순서
생성: initState → didChangeDependencies → build
갱신: setState → build
제거: dispose
기본 위젯 소개
| 위젯 | 용도 | 예시 |
|---|---|---|
Text |
텍스트 표시 | Text('안녕') |
Icon |
아이콘 표시 | Icon(Icons.star) |
Image |
이미지 표시 | Image.network(url) |
ElevatedButton |
버튼 | ElevatedButton(onPressed: ..., child: ...) |
TextField |
텍스트 입력 | TextField(controller: ...) |
Container |
박스 (크기, 색상, 여백) | Container(width: 100, color: Colors.blue) |
SizedBox |
고정 크기 공간 | SizedBox(height: 20) |
기본 위젯 예시
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('기본 위젯')),
body: Column(
children: [
// 텍스트
const Text(
'Flutter 학습',
style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
),
const SizedBox(height: 20), // 간격
// 아이콘
const Icon(Icons.flutter_dash, size: 50, color: Colors.blue),
const SizedBox(height: 20),
// 버튼
ElevatedButton(
onPressed: () {
print('버튼 클릭!');
},
child: const Text('클릭하세요'),
),
],
),
);
}
- [Flutter] 18. 빌드와 배포 - APK, App Store
- [Flutter] 17. 실전 프로젝트 - Todo 앱 만들기
- [Flutter] 16. 패키지 활용 - 유용한 패키지 소개
- [Flutter] 15. 디자인 - 테마, 스타일, 반응형
- [Flutter] 14. 로컬 저장소 - SharedPreferences, SQLite
- [Flutter] 13. HTTP 통신 - REST API 연동
- [Flutter] 12. 상태관리 - setState, Provider
- [Flutter] 11. 사용자 입력 - Form, TextField, 버튼
- [Flutter] 10. 화면 이동 - Navigation, Route
- [Flutter] 09. 리스트와 스크롤 - ListView, GridView
- [Flutter] 08. 레이아웃 - Row, Column, Stack
- [Flutter] 07. 위젯 기초 - StatelessWidget, StatefulWidget
- [Flutter] 06. Flutter 소개 및 개발환경 설치
- [Flutter] 05. Dart 비동기 - Future, async/await, Stream
- [Flutter] 04. Dart 클래스 - OOP 기초
- [Flutter] 03. Dart 함수 - 선언, 매개변수, 람다
- [Flutter] 02. Dart 제어문 - 조건문, 반복문
- [Flutter] 01. Dart 언어 기초 - 변수, 타입, 연산자