안녕하세요, 여러분!
오늘은 Flutter의 중요한 개념 중 하나인 StatefulWidget의 생명주기에 대해서 자세히 알아보겠습니다.
Flutter 에서 StatefulWidget은 사용자 인터페이스의 동적인 부분을 관리하는 데 사용되며, 화면의 상태 변화를 처리하고 반영하는데 주로 활용됩니다.
그런데 왜 위젯의 생명주기를 머릿속에 넣어둬야 할까요?
위젯의 생명주기를 알아야 언제 데이터를 주고 받을지와 화면이 없어질때 어떤 로직을 처리해야 할지를 정리해서 넣을 수 있습니다.
StatefulWidget은 Flutter에서 상태를 가진 위젯을 나타내는 클래스입니다.
StatefulWidget의 생명주기를 이해하는 것은 애플리케이션 개발과 유지보수에 매우 중요합니다.
아래는 StatefulWidget의 생명주기를 알아야 하는 이유에 대한 몇 가지 이유를 개인적으로 정리해보았습니다.
- UI 상태 관리: StatefulWidget은 상태를 가지는 위젯으로, 사용자 인터페이스의 상태를 관리하는 데 사용됩니다. 위젯이 화면에 표시되고 변경될 때마다 생명주기 메서드가 호출되며, 이를 통해 화면의 상태를 업데이트하고 반응적인 UI를 구현할 수 있습니다.
- 상태 변경 감지: StatefulWidget의 생명주기 메서드를 이용하면 상태의 변화를 감지하고, 이에 따라 필요한 작업을 수행할 수 있습니다. 예를 들어, 사용자의 입력에 따라 화면을 업데이트하거나 데이터를 로드하는 등의 작업을 수행할 수 있습니다.
- 자원 관리: 애플리케이션에서 사용되는 자원(메모리, 네트워크 등)을 효율적으로 관리하려면 StatefulWidget의 생명주기를 이해해야 합니다. 필요한 자원을 적절하게 할당하고 해제하는 작업을 생명주기 메서드 내에서 수행할 수 있습니다.
- 문제 해결 및 디버깅: 애플리케이션에서 예기치 않은 동작이나 버그가 발생했을 때 StatefulWidget의 생명주기를 분석하면 문제의 원인을 찾아낼 수 있습니다. 특정 생명주기 단계에서 발생하는 문제를 파악하여 수정할 수 있습니다.
- 성능 최적화: 상태 변화에 따른 화면 업데이트를 효율적으로 처리하여 성능을 최적화할 수 있습니다. 예를 들어, 불필요한 업데이트를 방지하거나 비용이 큰 작업을 최소화할 수 있습니다.
- 동작 예측: StatefulWidget의 생명주기를 이해하면 위젯의 동작을 예측할 수 있습니다. 화면이 언제 업데이트되는지, 어떤 순서로 메서드가 호출되는지 등을 알고 있으면 개발자가 의도한 동작을 보다 정확하게 제어할 수 있습니다.
요약하자면, StatefulWidget의 생명주기를 알아야 하는 이유는 애플리케이션의 UI 상태 관리, 상태 변경 감지, 자원 관리, 문제 해결 및 디버깅, 성능 최적화, 동작 예측 등 다양한 측면에서 개발과 유지보수의 품질을 높일 수 있기 때문입니다.
그럼, StatefulWidget 위젯의 생명주기를 간단하게 요약해 볼까요?
StatefulWidget 위젯의 생명주기는 아래와 같이 8가지로 구분할 수 있습니다.
1.createState():
StatefulWidget이 최초로 생성될 때, 먼저 createState() 메서드가 호출됩니다.
이 메서드는 StatefulWidget의 상태를 관리하는 State 객체를 생성합니다.
StatefulWidget은 상태가 변할 수 있는 요소이므로, 이 상태를 관리하는 State 클래스가 필요합니다.
2.initState():
createState() 메서드가 호출되고 나면, 이어서 initState() 메서드가 호출됩니다.
이 메서드는 State 객체가 초기화될 때 호출되며, 일회성 작업을 수행하는데 주로 사용됩니다.
예를 들어, 초기 데이터 로드나 컨트롤러 초기화 등이 여기에 해당합니다.
3.didChangeDependencies():
만약 상위 위젯이나 InheritedWidget 등의 종속성이 변경되면, didChangeDependencies() 메서드가 호출됩니다.
이 메서드는 처음 위젯이 생성될 때보다 많이 호출되는데, 이전에 의존성이 변경되었을 때 실행됩니다.
데이터를 가져오거나 업데이트하는데 활용할 수 있습니다.
4.build():
위의 단계들이 완료되면, Flutter 프레임워크는 build() 메서드를 호출하여 화면을 그립니다.
이 메서드에서는 사용자 인터페이스의 모습을 반환하는 역할을 합니다.
build() 메서드는 매번 상태가 변경될 때마다 호출되며, 화면을 업데이트하는데 사용됩니다.
5.didUpdateWidget():
상위 위젯이 다시 렌더링되어 해당 StatefulWidget이 재구성될 때, didUpdateWidget() 메서드가 호출됩니다.
여기서는 새로운 위젯과 이전 위젯의 차이점을 처리하는 로직을 구현할 수 있습니다.
6.setState():
사용자가 상호작용하여 StatefulWidget의 상태가 변할 때, setState() 메서드를 호출하여 상태를 업데이트합니다.
이 메서드를 호출하면 Flutter는 해당 위젯을 다시 렌더링하고 화면을 업데이트합니다.
7.deactivate():
StatefulWidget이 더 이상 활성 상태가 아니게 되면, deactivate() 메서드가 호출됩니다.
이 메서드는 위젯이 화면에서 제거되기 전에 호출되며, 필요한 정리 작업을 수행하는데 사용됩니다.
8.dispose():
StatefulWidget이 파괴될 때, dispose() 메서드가 호출됩니다.
이 메서드는 State 객체의 정리 작업을 수행하는데 사용되며, 메모리 누수를 방지하고 리소스를 해제하는데 중요합니다.
위에서 설명한 것처럼, StatefulWidget은 다양한 단계의 생명주기를 거쳐 화면을 업데이트하고 사용자의 상호작용을 처리합니다.
이러한 생명주기를 이해하고 정확히 활용할때 더 나은 앱으로 유저에게 깔끔한 서비스(?)를 제공할 수 있겠죠?
그럼, 간단한 예시 프로그램을 작성해서 제가 설명했던 개념들을 한개씩한개씩 머릿속에 쉽게 넣을 수 있도록 해보죠?
아래는 StatefulWidget 생명주기를 이해할 수 있도록 도움을 줄 수 있는 간단한 예시 프로그램 입니다.
각 생명주기단계별로 print 함수로 로그를 찍어봤고요. (위에서 알아본 생명주기 대로 동작하고 있는지요?)
프로그램을 간단하게 설명드리자면,
최초 화면에 아래와 같이 저의 삶의 Block 6 리스트가 뿌려져(?) 있습니다.
"운동하기", "독서하기", "코딩하기", "데보션블로그쓰기", "유튜브영상올리기", "육아하기"
그리고 FloatingButton 을 클릭하면 Block 6외에 "새로운 할일 0..1..2" 가 화면에 추가되는 프로그램입니다.
(우리가 인생을 산다는 것은 누구나 공평하게 주어지는 24시간의 삶에 자기 나름대로 얼마나 효율적인 방법으로 내가 사랑하는(?) 새로운 할일들을 추가할때? 삶이 변화할 수 있는거겠죠? )
그럼 제가 왜 해당 프로그램을 구현하게 되었을까요?
참고로 빌게이츠의 이야기인데요..
어느날 부자가 된 비결을 묻는 기자의 질문에 빌게이츠는 아래와 같이 대답했다고 합니다.
나는 매일 스스로에게 2가지 말을 반복한다라고요...그것은 바로..
하나 "왠지 오늘은 나에게 큰 행운이 생길것 같다" 이고
또 다른 하나는 " 나는 무엇이든 할 수 있다!" 라는 것이다 라고요...
아직 저는 너무나 부족하지만, 이런맥락에서 해당 프로그램을 준비해 봤습니다.
프로그램처럼 저의 Block 6에 새로운 할일 0,1,2...가 제 삶에 지속적으로 추가되면서 이런 새로운할일을 잘 감당하는 과정속에서 큰 행운이 생기고, 새로운 할일을 경험할 때 나는 절대 못해가 아닌, "나는 무엇이든 할 수 있어!" 라고 생각하자고요......
이런 마음으로 새로운 경험들을 체험하고 도전하면서 그곳에서 무엇을 남길 수 있을까? 라는 고민을 하면 정말로 나에게 소중한 삶의 경험으로 남더라고요... (그리고 그 경험을 토대로 저의 삶이 조금씩 변화하는것을 느낄 수 있었습니다. )
얼마전에 저는 ICT 2023 챌린지에 태풍을 뚫고(?) 작년에 이어서 멘토로 참여했는데요...
원래 저의 계획으로는 그 시간은 강원도로 휴가를 가있는 시간이었습니다.
하지만 태풍이 와서 저의 휴가계획은 미뤄지게 되었고요...
(이런말이 있죠? 계획은 사람이 세우나, 이루는 것은 하늘이라고요....)
아무튼, 원래 제가 계획했던 방향과는 다르게 ICT 2023 챌린지에 참여하게 되었죠..
행사에 참여하며, 데보션에서 정성스럽게 챙겨주신 쉑쉑버거와 함께 멘티와 기획서를 두고 이야기하는 가운데 새로운 인사이트를 저역시 가지게 되었고요..(와 이런 생각도 할수 있겠구나? 라고요)
비록 비오는 날 집에서 T타워까지 오가는 것이 어떤관점에서는 귀찮을 수 있겠지만,
그것을 감사하는 마음으로 이런 새로운 경험을 통해서 내 삶이 한단계 변화할 수 있는 선물이 그곳에 숨어있지 않을까? 라는 생각으로 다녀왔는데요..
정말 잘한것 같습니다. ㅎㅎ 비록 멘토링 결과가 어떻게 되었든...
저나름대로 온맘다해서 멘토링을 열심히 수행했고요...
특히 주제가 저의 Block 6안에 있는 유튜브 관련 수익에 대한 부분이라서 더 열심히 했던것 같네요~~
아무튼 저의 실무에서 산전수전 경험을 토대로한 조언이 멘티에게 조금이나마 도움이 되었기를 간절히 바래봅니다...
아무튼, 삼천포로 빠졌던 ICT 챌린지 2023 멘토링 후기 이야기를 뒤로하고...(블로그를 이어나갈께요~ )
import 'package:flutter/material.dart';
void main() {
runApp(TodoListApp());
}
class TodoListApp extends StatefulWidget {
@override
_TodoListAppState createState() {
print('createState() 호출됨');
return _TodoListAppState();
}
}
class _TodoListAppState extends State<TodoListApp> {
List<String> todos = ['운동하기', '독서하기', '코딩하기', '데보션블로그쓰기', '유튜브영상올리기', '육아하기'];
int _count = 0;
@override
void initState() {
super.initState();
print('initState() 호출됨');
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
print('didChangeDependencies() 호출됨');
}
@override
void didUpdateWidget(TodoListApp oldWidget) {
super.didUpdateWidget(oldWidget);
print('didUpdateWidget() 호출됨');
}
@override
void deactivate() {
print('deactivate() 호출됨');
super.deactivate();
}
@override
void dispose() {
print('dispose() 호출됨');
super.dispose();
}
void addTodo() {
setState(() {
print('setState() 호출됨, _count: $_count');
todos.add('새로운 할 일: $_count');
_count++;
});
}
@override
Widget build(BuildContext context) {
print('build() 호출됨');
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('할 일 목록')),
body: ListView.builder(
itemCount: todos.length,
itemBuilder: (context, index) {
return ListTile(title: Text(todos[index]));
},
),
floatingActionButton: FloatingActionButton(
onPressed: addTodo,
child: Icon(Icons.add),
),
),
);
}
}
그럼 위의 프로그램을 토대로 위의 개념을 설명해 보도록 할께요~
createState(): StatefulWidget을 생성하고, 상태를 관리하는 State 객체를 생성합니다.
class TodoListApp extends StatefulWidget {
@override
_TodoListAppState createState() {
print('createState() 호출됨');
return _TodoListAppState();
}
}
initState(): 앱이 시작될 때 초기 상태를 설정하거나 초기 데이터를 로드합니다.
초기 데이터는 저의 Block 6 를 리스트로 넣어두었죠..
class _TodoListAppState extends State<TodoListApp> {
List<String> todos = ['운동하기', '독서하기', '코딩하기', '데보션블로그쓰기', '유튜브영상올리기', '육아하기'];
int _count = 0;
@override
void initState() {
super.initState();
print('initState() 호출됨');
}
// ...
}
didChangeDependencies(): 종속성(의존성)이 변경될 때 호출되며, 여기서는 예를 들어 언어 설정 변경 시 데이터를 업데이트하는 작업을 수행할 수 있습니다.
@override
void didChangeDependencies() {
super.didChangeDependencies();
print('didChangeDependencies() 호출됨');
}
build(): UI를 렌더링하고 화면에 나타냅니다.
@override
Widget build(BuildContext context) {
print('build() 호출됨');
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('할 일 목록')),
body: ListView.builder(
itemCount: todos.length,
itemBuilder: (context, index) {
return ListTile(title: Text(todos[index]));
},
),
),
);
}
setState(): 사용자의 상호작용으로 상태가 변경될 때 해당 상태를 업데이트하고 화면을 다시 그립니다.
void addTodo() {
setState(() {
print('setState() 호출됨, _count: $_count');
todos.add('새로운 할 일: $_count');
_count++;
});
didUpdateWidget(): 위젯이 업데이트될 때 새로운 위젯과 이전 위젯의 차이점을 처리하는 로직을 구현할 수 있습니다.
@override
void didUpdateWidget(TodoListApp oldWidget) {
super.didUpdateWidget(oldWidget);
print('didUpdateWidget() 호출됨');
}
deactivate(): 다른 화면으로 이동할 때 호출되며, 필요한 정리 작업을 수행합니다.
@override
void deactivate() {
print('deactivate() 호출됨');
super.deactivate();
}
dispose(): 위젯이 파괴될 때 호출되며, 리소스 정리 등의 작업을 수행합니다.
@override
void dispose() {
print('dispose() 호출됨');
super.dispose();
}
위에서는 예시 프로그램을 토대로 StatefulWidget의 생명주기에 대해서 간단하게 설명해 보았고요.
이제 앱을 실행하고 위젯의 생명주기와 상태 변화를 로그로 확인해 볼께요~
아래는 최초 화면이고요..
플로팅버튼을 세번 클릭하면 아래와 같이 새로운 할일 0,1,2 추가되는 간단한 프로그램입니다. (정말간단하죠? ㅎㅎ)
로그는 아래와 같습니다. 아래와 같이 setState() 함수가 3번 호출되었죠?
아무튼 Flutter의 위젯 생명주기 대한 간략한 설명을 마치겠습니다.
다음에는 실제 프로젝트에서 이러한 개념을 적용하여 더 멋진 앱을 개발해보는 것이 저만의 목표입니다.
오늘의 블로그는 여기까지고요
항상 믿고 봐주셔서 감사합니다!
그럼, 결론을 정리해보도록 하겠습니다.
결론
오늘은 Flutter의 중요한 개념 중 하나인 StatefulWidget의 생명주기에 대해서 간단하게 알아보았습니다.
아래와 같이 8가지 단계로 나누어져 있고요.. 아래 8가지는 꼭 머릿속에 넣어두시면 좋겠죠?
1.createState(): StatefulWidget이 최초로 생성될 때, 먼저 createState() 메서드가 호출됩니다.
2.initState(): createState() 메서드가 호출되고 나면, 이어서 initState() 메서드가 호출됩니다.
3.didChangeDependencies(): 만약 상위 위젯이나 InheritedWidget 등의 종속성이 변경되면, didChangeDependencies() 메서드가 호출됩니다.
4.build(): 위의 단계들이 완료되면, Flutter 프레임워크는 build() 메서드를 호출하여 화면을 그립니다.
5.didUpdateWidget(): 상위 위젯이 다시 렌더링되어 해당 StatefulWidget이 재구성될 때, didUpdateWidget() 메서드가 호출됩니다.
6.setState(): 사용자가 상호작용하여 StatefulWidget의 상태가 변할 때, setState() 메서드를 호출하여 상태를 업데이트합니다. 이 메서드를 호출하면 Flutter는 해당 위젯을 다시 렌더링하고 화면을 업데이트합니다.
7.deactivate(): StatefulWidget이 더 이상 활성 상태가 아니게 되면, deactivate() 메서드가 호출됩니다.
이 메서드는 위젯이 화면에서 제거되기 전에 호출되며, 필요한 정리 작업을 수행하는데 사용됩니다.
8.dispose():StatefulWidget이 파괴될 때, dispose() 메서드가 호출됩니다.
이 메서드는 State 객체의 정리 작업을 수행하는데 사용되며, 메모리 누수를 방지하고 리소스를 해제하는데 중요합니다.
물론 해당 프로그램에서는 didUpdateWidget(), deactivate(), dispose() 는 빠져있는데요..
아직은 화면 이동을 다루지 않았으므로 호출되지 않았죠?
앞으로 Flutter 에 대해서 공부하며, 블로깅을 하면서 생명 주기에 대해서 알아볼거니깐요...기대해 주세요~ㅎㅎ
엇! 눈씻고 찾아봐도 idUpdateWidget(), deactivate(), dispose() 는 빠져있는데? 라고 생각하시지마시고요..
언제 저 함수가 호출될까? 라는 궁금증으로 제 블로그를 시청해주세요~~^^;
그리고, StatefulWidget의 생명주기를 알아야 하는 이유에 대해서도 간단하게 머릿속에 정리해두시길 추천드립니다.
혹시나 이 블로그가 삶(?)을 살아가시는데 조금이나마 도움이 되셨다면,
제가 얼마전에 네이버 인플루언서에 선정되었거든요...
(아래 네이버 인플루언서의 팬이 되주시면, IT외에 제 개인적인 관심사인 경제, 부동산, 주식관련해서 정성스럽게 만든 저만의 컨텐츠를 받아보실수 있습니다. ^^;)
'좋아하는 것_매직IT > 19.flutter' 카테고리의 다른 글
Naver Papago Openapi 를 활용한 간단한 번역 기능 앱 만들기 (0) | 2023.09.12 |
---|---|
플러터(Flutter) 앱을 구성하는 위젯(Widget) 개념 정리해보기. (ft.부의 추월차선 서막!) (0) | 2023.06.18 |
flutter와 함께하는 openai 관련 Completions api 공부하기 (ft.openai_client) (0) | 2023.02.13 |
1.flutter, 플러터(flutter)에 대해서 알아볼까요? (0) | 2021.02.07 |