Youtube 코딩셰프님의 강의를 요약 정리한 글이다. dart 언어나 이론 부분은 자바와 유사하여 대부분 제외하였고, flutter 기초 위주로 정리한다.
https://www.youtube.com/@codingchef
1. State Management
state: UI에 변화가 생기도록 영향을 미치는 데이터
데이터에는 앱 수준의 데이터, 위젯 수준의 데이터가 있다.
앱 수준은 로그인 등 전체 앱에 영향을 미치는 데이터, 위젯 수준은 해당 위젯에만 영향을 미치는 데이터를 의미한다.
플러터는 기본적으로 state가 변하면 hot reload를 하여 화면을 갱신한다.
그리고 이를 위해 setState() 메서드를 사용한다. Build method를 호출하는 방법인데, Flutter가 제공하는 state management의 기본적인 방법이라고 보면 된다.
setState() 메서드 문제점
setState() 메서드의 문제점 1. 하위 위젯의 상태변화를 위해 상위 위젯의 상태 변화도 일어남
강의에 나온 아래 예시 그림을 보면, 맨 아래 Text가 PlusCounter, MinusCounter에 의해 변경이 필요한 상황일 때, MyPage에 정의된 SetState를 통해 변경이 일어나게 한다면 하위의 Plus, Minus 위젯 -> 각 Button -> 각 Text를 변경하기 위해서 최상위인 MyPage에서 최하위까지 모두 상태 변경이 일어나는 상황이 발생한다.
기본 setState()를 사용하면 확실하게 상태변환은 가능하나, 이런 비효율적인 부분이 발생할 수 있다.
setState() 메서드의 문제점2. 같은 상태를 공유하는 여러 위젯에서, 한 위젯의 상태변화를 다른 위젯이 알 방법이 없음
만약 Plus 위젯과 Minus 위젯이 같은 상태를 가져야하는 변수를 갖고 있다면 Plus 위젯의 setState() 호출만으로는 Minus 위젯에서 Plus 위젯에서의 상태 변화를 알 수 없는 문제가 있다.
State Management 정의
1. 위젯의 위치에 상관없이 필요한 데이터에 쉽게 접근할 수 있는 방법
2. 변화된 데이터에 맞추어 UI를 다시 그려주는 기능이 포함
실습 해보기
강의에서는 위 여러 위젯들이 계층 구조를 가질 때처럼 Provider를 이해하기 위해서 어부와 매운탕 집 예시를 든다. 이를 통해 아래 그림처럼 Provider 문법을 설명한다.
Provider는 High, Middle, Low 위젯에 위치한 각각의 매운탕집 SpicyA, SpicyB, SpicyC 위젯에 데이터를 공급하는 전달자 역할을 한다.
데이터의 타입은 Salmon이라는 생선을 예시로 들고, context는 수로를 의미한다. 산 최정상에서 수로를 통해 각 위치에 있는 매운탕집들에 생선을 보내는데, context라는 수로를 갖는 곳에만 Provider가 데이터를 전달할 수 있는 것이다. 그리고 context를 갖고 있는 점에서
유추할 수 있듯이 Provider도 flutter에서의 하나의 위젯처럼 동작한다는 것을 기억하면 좋을 것 같다.
Provider 적용
Provider는 데이터를 필요로하는 위젯보다 항상 상위에 위치해야한다.
pub.dev에서 provider의 의존성을 추가한다. 그리고 강의 예제 코드에서 최상위 MaterialApp을 Provider 위젯으로 감싼다.
create라는 속성값에 context를 포함한, 내가 전달할 데이터를 정의해주면된다. required 인자이다.
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return Provider(
create: (context) => FishModel(name: 'Salmon', number: 10, size: 'big'),
child: MaterialApp(
home: FishOrder(),
),
);
}
}
그리고 이렇게 전달될 데이터를 아래처럼 하위 위젯들에서 참조하면 된다.
class FishOrder extends StatelessWidget {
const FishOrder({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Fish Order'),
),
body: Center(
child: Column(
children: [
Text(
'Fish name: ${Provider.of<FishModel>(context).name}',
style: TextStyle(fontSize: 20),
),
SizedBox(
height: 20,
),
High()
],
),
)
);
}
}
참고로 of 메서드는 가장 가까운 상위에서 context를 거슬러 올라가면서 원하는 타입의 인스턴스를 반환하는 기능을 갖는다.
위와 같이 적용 후 앱을 실행해보면 정상적으로 처리되는 것을 확인할 수 있다.
inspector로 확인해보면 앱은 이런 구조이다. 만약 provider를 사용하지 않았다면 최상위에서 FishModel을 하나 생성하고 그 인스턴스를 계속해서 하위 위젯들에 전달해주어야 했을 것이다.
'Programming-[CrossPlatform] > Flutter' 카테고리의 다른 글
Flutter Provider: 3. GetX - Simple State Manager (0) | 2025.01.06 |
---|---|
Flutter Provider: 2. ChangeNotifierProvider, MultiProvider (1) | 2025.01.02 |
[작성중][제철음식 알리미] bottomNavBar, didChangeDependencies, pageController (1) | 2024.10.22 |
[제철음식 알리미] ValueListenableBuilder, ValueNotifier (0) | 2024.10.21 |
[제철음식 알리미] 2. 화면 요소: Flexible, Expanded, Positioned (1) | 2024.10.20 |