Flutter 앱 라이프사이클에 대해 설명해주세요
질문
Flutter 앱 라이프사이클에 대해 설명해주세요.
답변
Flutter 앱 라이프사이클은 앱이 시작되고, 실행되며, 종료되는 과정에서 거치는 여러 상태와 이벤트를 의미합니다. Flutter에서는 크게 두 가지 수준의 라이프사이클이 있습니다: 앱 수준 라이프사이클과 위젯 수준 라이프사이클입니다.
1. 앱 수준 라이프사이클
앱 수준 라이프사이클은 WidgetsBindingObserver
를 통해 관찰할 수 있으며, 앱이 전체적으로 경험하는 상태 변화를 나타냅니다.
앱 라이프사이클 상태
AppLifecycleState
열거형은 다음 상태들을 정의합니다:
detached: 앱이 플랫폼 뷰에 연결되지 않은 상태입니다. 주로 앱이 시작되기 전이나 종료된 후에 발생합니다.
inactive: 앱이 시각적으로 보이지만 사용자 입력을 받지 않는 상태입니다. iOS에서는 앱 전환기를 열 때, 전화가 오거나 다른 시스템 알림이 뜰 때 발생합니다. Android에서는 이 상태가 거의 발생하지 않습니다.
paused: 앱이 현재 보이지 않고, 사용자 입력을 받지 않으며, 백그라운드에서 실행 중인 상태입니다. 사용자가 다른 앱으로 전환했거나 홈 화면으로 갔을 때 발생합니다.
resumed: 앱이 보이고 사용자 입력에 응답하는 상태입니다. 앱이 포그라운드에서 완전히 활성화된 상태입니다.
hidden: Flutter 3.13부터 추가된 상태로, 앱이 시스템 네비게이션에 가려져 완전히 보이지 않지만 여전히 활성 상태인 경우입니다.
앱 라이프사이클 감지 방법
WidgetsBindingObserver
를 구현하고 didChangeAppLifecycleState
메서드를 오버라이드하여 앱 라이프사이클 변화를 감지할 수 있습니다:
class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
switch (state) {
case AppLifecycleState.resumed:
print("앱이 포그라운드에 있고 사용자 입력을 받고 있습니다.");
break;
case AppLifecycleState.inactive:
print("앱이 활성 상태가 아니고 사용자 입력을 받지 않습니다.");
break;
case AppLifecycleState.paused:
print("앱이 현재 사용자에게 보이지 않고, 백그라운드에서 실행 중입니다.");
break;
case AppLifecycleState.detached:
print("앱이 호스트 뷰에서 분리되었지만 플러터 엔진은 계속 실행 중입니다.");
break;
case AppLifecycleState.hidden:
print("앱이 시스템 네비게이션에 가려져 있습니다.");
break;
}
}
@override
Widget build(BuildContext context) {
return MaterialApp(...);
}
}
2. 위젯 수준 라이프사이클
위젯 수준 라이프사이클은 개별 위젯(특히 Stateful 위젯)의 생성, 업데이트, 제거 과정을 다룹니다.
StatefulWidget 라이프사이클
- createState(): StatefulWidget이 생성될 때 호출되며, 연결된 State 객체를 생성합니다.
- initState(): State 객체가 트리에 삽입될 때 한 번만 호출됩니다. 이곳에서 초기화 작업을 수행합니다.
- didChangeDependencies(): initState() 후에 호출되며, 위젯이 의존하는 InheritedWidget이 변경될 때마다 호출됩니다.
- build(): 위젯의 UI를 구성합니다. 이 메서드는 initState() 후, didUpdateWidget() 후, setState()가 호출된 후, 또는 의존성이 변경될 때마다 호출됩니다.
- didUpdateWidget(): 부모 위젯이 재구성되어 이 위젯을 새 위젯으로 업데이트할 때 호출됩니다(같은 runtimeType과 key를 가진 경우).
- setState(): 위젯의 내부 상태가 변경될 때 호출되어 Flutter에게 위젯을 다시 빌드하도록 알립니다.
- deactivate(): State 객체가 위젯 트리에서 일시적으로 제거될 때 호출됩니다. 위젯이 트리에서 이동할 때 발생할 수 있습니다.
- dispose(): State 객체가 위젯 트리에서 영구적으로 제거될 때 호출됩니다. 리소스를 해제하는 코드를 여기에 작성합니다.
class MyWidget extends StatefulWidget {
@override
_MyWidgetState createState() => _MyWidgetState(); // 1. createState
}
class _MyWidgetState extends State<MyWidget> {
@override
void initState() { // 2. initState
super.initState();
print("initState 호출");
}
@override
void didChangeDependencies() { // 3. didChangeDependencies
super.didChangeDependencies();
print("didChangeDependencies 호출");
}
@override
Widget build(BuildContext context) { // 4. build
print("build 호출");
return Container();
}
@override
void didUpdateWidget(MyWidget oldWidget) { // 5. didUpdateWidget
super.didUpdateWidget(oldWidget);
print("didUpdateWidget 호출");
}
@override
void deactivate() { // 7. deactivate
print("deactivate 호출");
super.deactivate();
}
@override
void dispose() { // 8. dispose
print("dispose 호출");
super.dispose();
}
}
3. 라이프사이클 활용 사례
백그라운드/포그라운드 전환 처리
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
if (state == AppLifecycleState.paused) {
// 앱이 백그라운드로 갈 때 데이터 저장
saveUserData();
} else if (state == AppLifecycleState.resumed) {
// 앱이 포그라운드로 돌아올 때 데이터 새로고침
refreshData();
}
}
리소스 관리
@override
void initState() {
super.initState();
// 위젯 생성 시 리소스 초기화
videoController = VideoPlayerController.network('...')..initialize();
}
@override
void dispose() {
// 위젯 제거 시 리소스 해제
videoController.dispose();
super.dispose();
}
상태 관리
@override
void didUpdateWidget(OldWidget oldWidget) {
super.didUpdateWidget(oldWidget);
if (widget.someProperty != oldWidget.someProperty) {
// 속성이 변경되었을 때 상태 업데이트
_updateInternalState();
}
}
요약
Flutter 앱 라이프사이클은 앱의 상태 변화와 위젯의 생명주기를 이해하고 관리하는 데 중요합니다. 앱 수준 라이프사이클은 앱의 전체적인 상태(resumed, paused, inactive 등)를 다루고, 위젯 수준 라이프사이클은 개별 위젯의 생성부터 제거까지의 과정을 관리합니다. 이러한 라이프사이클 이벤트를 적절히 활용하면 리소스 관리, 상태 보존, 앱 성능 최적화 등을 효과적으로 수행할 수 있습니다.