Riverpod이란?
원래 Flutter에는 Provider라는 공식 추천 상태 관리 라이브러리가 있습니다. 하지만 Provider는 위젯 트리(BuildContext)에 강하게 종속되어 있어, 트리가 복잡해지면 에러가 런타임에 발생하는 치명적인 단점이 존재했습니다.
이를 해결하기 위해 만든 것이 Riverpod입니다.
- 장점 1: 컴파일 타임에 안전합니다. (앱 실행 전에 에러를 잡을 수 있음)
- 장점 2: Flutter 위젯 트리(BuildContext)에 의존하지 않고 어디서든 상태를 읽을 수 있습니다.
- 장점 3: 캐싱과 비동기(API 통신 등) 처리가 내장되어 있어 매우 강력합니다.
설치
name: my_app_name
environment:
sdk: ^3.7.0
flutter: ">=3.0.0"
dependencies:
flutter:
sdk: flutter
flutter_riverpod: ^3.2.1
사용
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
// 값을 저장할 "provider"를 생성합니다(여기서는 "Hello world").
// provider를 사용하면 노출된 값을 모의(mock)//재정의(override)할 수 있습니다.
final helloWorldProvider = Provider((_) => 'Hello world');
void main() {
runApp(
// 위젯이 providers를 읽을 수 있게 하려면 전체 애플리케이션을 "ProviderScope" 위젯으로 감싸야 합니다.
// 여기에 providers의 상태가 저장됩니다.
ProviderScope(
child: MyApp(),
),
);
}
// Riverpod에 의해 노출되는 StatelessWidget 대신 ConsumerWidget을 확장합니다.
class MyApp extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final String value = ref.watch(helloWorldProvider);
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('Example')),
body: Center(
child: Text(value),
),
),
);
}
}
Swift와 비교
| Flutter(Riverpod) | SwiftUI(Combine) | 역할 |
|---|---|---|
| ProviderScope | @main안의 최상위 환경 세팅 |
상태들을 담아두는 거대한 전역 컨테이너 |
| Provider | @StateObject, ObservableObject |
상태(데이터)를 정의하고 관리하는 객체 |
| WidgetRef(ref) | @EnvironmentObject나 객체 접근자 |
위젯에서 상태를 읽어오기 위한 다리 역할 |
| ref.watch() | @ObservedObject/@Published |
상태 값이 변하면 UI를 자동으로 다시 그림 |
| ref.read() | 버튼 액션 안에서 객체 메서드 호출 | UI를 다시 그리지 않고 값만 일회성으로 읽거나 함수 실행 |
Riverpod의 3가지 핵심 동작
Riverpod에서 데이터를 사용할 때는 ref라는 객체를 통해 다음 3가지 동작을 합니다.
ref.watch(provider): 데이터를 구독합니다. 값이 바뀌면 화면을 새로고침 합니다. 주로 UI를 그릴 때 사용합니다.ref.read(provider.notifier).method(): 데이터를 일회성으로 읽고 맙니다. 값이 바뀌어도 화면을 갱신하지 않습니다. 주로 버튼 클릭 이벤트, API 호출 함수 등을 실행할 때 사용합니다.ref.listen(provider, (prev, next)): 데이터가 바뀔 때 UI 트리를 다시 그리는 대신, 특정 액션만 취합니다.(예: 에러가 나면 알림창(SnackBar) 띄우기, 화면 이동하기) iOS의 Combinesink나 SwiftUI의.onChange()와 같습니다.
