티스토리 뷰
[Flutter] Widget Lifecycle 이해하기: Stateful vs Stateless
doyeonjeong_ 2025. 3. 13. 09:33
Flutter에서 앱을 개발하다 보면 Widget
의 라이프사이클을 이해하는 것이 매우 중요하다.
Flutter의 Widget
은 UI를 구성하는 기본 단위로, Stateful Widget
과 Stateless Widget
으로 나뉘는데
각 Widget은 생성, 업데이트, 제거 등의 과정을 거치며, 이 과정을 라이프사이클이라고 부른다.
1. Stateless Widget Lifecycle
Stateless Widget
은 상태를 가지지 않는 위젯으로,
데이터가 변하지 않는 정적인 UI를 렌더링할 때 사용된다.
- Create: Widget이 처음 생성될 때 호출
- build(): UI를 빌드하여 화면에 표시
- dispose: Widget이 화면에서 제거될 때 호출
Stateless Widget
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
print('Building MyHomePage'); // build() 호출 시 로그 출력
return Scaffold(
appBar: AppBar(title: Text('Stateless Widget Example')),
body: Center(child: Text('Hello, Stateless World!')),
);
}
// dispose는 Stateless Widget에서는 직접 호출되지 않음
@override
void dispose() {
print('Disposing MyHomePage');
super.dispose();
}
}
Stateless Widget
은 build()
메서드만 주로 사용되며, 상태 변화가 없으므로 dispose
는 명시적으로 호출되지 않는다. 위 코드에서 build()
가 호출될 때마다 UI가 갱신된다.
2. Stateful Widget Lifecycle
Stateful Widget
은 상태를 가지는 위젯으로, 사용자 입력이나 데이터 변화에 따라 UI가 동적으로 업데이트된다.
- Create Widget: Widget이 처음 생성될 때 호출
- Create State:
State
객체 초기화. 여기서initState()
가 호출되어 초기 상태를 설정 - initState(): Widget이 화면에 추가될 때 한 번만 호출, 초기화 수행
- build(): UI를 빌드하여 화면에 표시. 상태가 변경될 때마다 다시 호출
- setState() / didUpdateWidget(): 상태가 변경되거나 위젯이 업데이트될 때 호출.
setState()
통해 UI 갱신 가능 - deactivate: Widget이 비활성화될 때 호출(예: 화면에서 일시적으로 제거)
- dispose(): Widget이 완전히 제거될 때 호출, 리소스 해제
Stateful Widget
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
@override
void initState() {
super.initState();
print('initState: Initializing state');
}
@override
void didUpdateWidget(covariant MyHomePage oldWidget) {
super.didUpdateWidget(oldWidget);
print('didUpdateWidget: Widget updated');
}
@override
void deactivate() {
super.deactivate();
print('deactivate: Widget is being deactivated');
}
@override
void dispose() {
super.dispose();
print('dispose: Widget is disposed');
}
void _incrementCounter() {
setState(() {
_counter++;
print('setState: Counter incremented to $_counter');
});
}
@override
Widget build(BuildContext context) {
print('build: Rebuilding UI');
return Scaffold(
appBar: AppBar(title: Text('Stateful Widget Example')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('You have pushed the button this many times:'),
Text('$_counter', style: TextStyle(fontSize: 24)),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
initState()
는 위젯이 처음 생성될 때 호출되어 초기 상태(_counter = 0
)를 설정한다.build()
는 UI를 렌더링하며,setState()
가 호출될 때마다 다시 실행된다.didUpdateWidget()
은 위젯의 속성이 변경될 때 호출되며, 상태 갱신 로직을 추가할 수 있다.deactivate
와dispose
는 위젯이 화면에서 제거될 때 리소스를 정리하는 데 사용된다.
3. Stateful vs Stateless: 사용하는 경우
- Stateless Widget: UI가 고정되어 있고 상태 변화가 필요 없는 경우(예: 텍스트, 이미지) 사용.
- Stateful Widget: 사용자 입력이나 데이터 변화에 따라 UI가 동적으로 변해야 하는 경우(예: 카운터, 폼) 사용.
결론
모바일은 웹보다 상대적으로 작은 화면이라서 잦은 상태관리를 필요로 한다..
이렇게 복잡한 상태관리를 위해 Riverpod, Flutter Hooks, Bloc, GetX 등 여러 패키지가 존재하지만
최근에 많은 의존성 때문에 빌드 에러를 자주 겪어서 그런지 요즘은 되도록이면 바닐라한 코드(?)로 작성하려고 한다...
어차피 많은 패키지들도 결국은 기본 코드에서 시작하는 거고, 플러터가 업데이트 될 수록 같이 업데이트 해줘야 하는 의존성이 늘어나는 거니까... 기본에 충실하자 😢
'Developments > Flutter' 카테고리의 다른 글
Flutter Lints 와 analysis_options (0) | 2025.03.07 |
---|---|
Dart의 생성자를 ㅇrㄹr보좌.. (0) | 2025.03.05 |
[Flutter] 3.7 업데이트 살펴보기 (3) (0) | 2025.02.14 |
[Flutter] 3.7 업데이트 살펴보기 (2) (0) | 2025.02.13 |
[Flutter] 3.7 업데이트 살펴보기 (1) (0) | 2025.02.11 |
- Total
- Today
- Yesterday
- 오블완챌린지
- 렌더링최적화
- jsonkey
- 플러터
- 낙관적 업데이트 패턴
- flutter 3.7
- 플러터네이티브
- swiftmigration
- flutter updates
- 티스토리챌린지
- 플러터ios애니메이션
- ios
- fromjson()
- sliverlist
- lints
- 플러터 업데이트
- 플러터업데이트
- flutter3.7
- tojson()
- SWIFT
- llm 설치
- flutter
- sliver
- analysis_options
- jsonserializable
- 개발신입
- slivers
- 다트문법
- flutter_lints
- 오블완
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |