Search

Riverpod

Riverpod

: Flutter ์ƒํƒœ๊ด€๋ฆฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ
Riverpod์€ Flutter ๊ณต์‹ ์ƒํƒœ๊ด€๋ฆฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ธ Provider์˜ ๊ฐœ์„ ๋œ ๋ฒ„์ „์œผ๋กœ, ๋” ์•ˆ์ „ํ•˜๊ณ  ๊ฐ•๋ ฅํ•œ ์ƒํƒœ ๊ด€๋ฆฌ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

Riverpod์˜ ์ฃผ์š” ํŠน์ง•

1.
์ „์—ญ ์ƒํƒœ ๊ด€๋ฆฌ ๊ฐ€๋Šฅ
โ€ข
Provider์ฒ˜๋Ÿผ BuildContext๊ฐ€ ํ•„์š”ํ•˜์ง€ ์•Š์Œ โ†’ ์ „์—ญ์—์„œ ์ƒํƒœ ๊ด€๋ฆฌ ๊ฐ€๋Šฅ
2.
์•ˆ์ „ํ•œ ์ƒํƒœ ๊ด€๋ฆฌ
โ€ข
StateNotifier๋ฅผ ์‚ฌ์šฉํ•ด ๋ถˆ๋ณ€ ์ƒํƒœ ๊ด€๋ฆฌ ์ง€์›
โ€ข
FutureProvider, StreamProvider๋กœ ๋น„๋™๊ธฐ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ๊ฐ€๋Šฅ
3.
์˜์กด์„ฑ ์ฃผ์ž…(DI) ์ง€์›
โ€ข
์—ฌ๋Ÿฌ Provider ๊ฐ„ ์˜์กด ๊ด€๊ณ„๋ฅผ ์‰ฝ๊ฒŒ ์„ค์ • ๊ฐ€๋Šฅ
4.
ref.watch, ref.read, ref.listen ํ™œ์šฉ ๊ฐ€๋Šฅ
โ€ข
ref.watch() โ†’ ์ƒํƒœ๊ฐ€ ๋ณ€๊ฒฝ๋  ๋•Œ๋งˆ๋‹ค UI ์—…๋ฐ์ดํŠธ
โ€ข
ref.read() โ†’ ์ƒํƒœ ๊ฐ’์„ ์ฆ‰์‹œ ๊ฐ€์ ธ์˜ค์ง€๋งŒ UI ๋ฆฌ๋ Œ๋”๋ง ์—†์Œ
โ€ข
ref.listen() โ†’ ํŠน์ • ๊ฐ’์ด ๋ณ€๊ฒฝ๋  ๋•Œ ์ฝœ๋ฐฑ ์‹คํ–‰

Riverpod ์„ค์น˜

flutter pub add flutter_riverpod
Shell
๋ณต์‚ฌ
๋˜๋Š”
dependencies: flutter_riverpod: latest_version
YAML
๋ณต์‚ฌ

Riverpod ๊ธฐ๋ณธ ์‚ฌ์šฉ๋ฒ•

Provider ์‚ฌ์šฉํ•˜๊ธฐ (๊ธฐ๋ณธ ์ƒํƒœ ๊ด€๋ฆฌ)

import 'package:flutter_riverpod/flutter_riverpod.dart'; // ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•  Provider ์„ ์–ธ final counterProvider = StateProvider<int>((ref) => 0); void main() { runApp(ProviderScope(child: MyApp())); } class MyApp extends ConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { final count = ref.watch(counterProvider); // ์ƒํƒœ ๊ฐ์ง€ return Scaffold( appBar: AppBar(title: Text('Riverpod Example')), body: Center( child: Text('Count: $count', style: TextStyle(fontSize: 24)), ), floatingActionButton: FloatingActionButton( onPressed: () => ref.read(counterProvider.notifier).state++, // ์ƒํƒœ ์—…๋ฐ์ดํŠธ child: Icon(Icons.add), ), ); } }
Dart
๋ณต์‚ฌ
์„ค๋ช…
โ€ข
StateProvider<int> โ†’ ๊ธฐ๋ณธ์ ์ธ ์ƒํƒœ ์ œ๊ณต (์ดˆ๊ธฐ๊ฐ’ 0)
โ€ข
ref.watch(counterProvider) โ†’ ์ƒํƒœ ๋ณ€๊ฒฝ ์‹œ UI ์ž๋™ ์—…๋ฐ์ดํŠธ
โ€ข
ref.read(counterProvider.notifier).state++ โ†’ ๊ฐ’ ๋ณ€๊ฒฝ

StateNotifierProvider ์‚ฌ์šฉํ•˜๊ธฐ (๋ณต์žกํ•œ ์ƒํƒœ ๊ด€๋ฆฌ)

import 'package:flutter_riverpod/flutter_riverpod.dart'; class CounterNotifier extends StateNotifier<int> { CounterNotifier() : super(0); void increment() => state++; } // StateNotifierProvider ์‚ฌ์šฉ final counterProvider = StateNotifierProvider<CounterNotifier, int>((ref) => CounterNotifier()); class CounterScreen extends ConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { final count = ref.watch(counterProvider); return Scaffold( body: Center(child: Text('Count: $count')), floatingActionButton: FloatingActionButton( onPressed: () => ref.read(counterProvider.notifier).increment(), child: Icon(Icons.add), ), ); } }
Dart
๋ณต์‚ฌ
StateNotifier๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ณต์žกํ•œ ๋กœ์ง์„ ์‰ฝ๊ฒŒ ๊ด€๋ฆฌ ๊ฐ€๋Šฅ!

FutureProvider ์‚ฌ์šฉํ•˜๊ธฐ (๋น„๋™๊ธฐ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ)

final futureProvider = FutureProvider<String>((ref) async { await Future.delayed(Duration(seconds: 2)); // 2์ดˆ ํ›„ ๋ฐ์ดํ„ฐ ๋ฐ˜ํ™˜ return "Hello, Riverpod!"; }); class AsyncScreen extends ConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { final asyncValue = ref.watch(futureProvider); return Scaffold( body: Center( child: asyncValue.when( data: (data) => Text(data), loading: () => CircularProgressIndicator(), error: (err, stack) => Text('Error: $err'), ), ), ); } }
Dart
๋ณต์‚ฌ
FutureProvider๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด API ์š”์ฒญ, DB ํ˜ธ์ถœ ๋“ฑ ๋น„๋™๊ธฐ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ๋ฅผ ์‰ฝ๊ฒŒ ๊ด€๋ฆฌ ๊ฐ€๋Šฅ

GetX vs Bloc vs Provider vs Riverpod ๋น„๊ต

๊ธฐ๋Šฅ
GetX
Bloc
Provider
Riverpod
์ƒํƒœ ๊ด€๋ฆฌ
๊ฐ„ํŽธํ•จ (obs, GetBuilder)
๊ตฌ์กฐ์  (Cubit, Bloc)
๊ธฐ๋ณธ (ChangeNotifier)
๊ฐ•๋ ฅํ•จ (StateNotifier, Notifier)
๋น„๋™๊ธฐ ์ƒํƒœ ๊ด€๋ฆฌ
RxDart ์—†์ด ๊ฐ€๋Šฅ (FutureBuilder ์—†์ด๋„ ๊ฐ€๋Šฅ)
BlocObserver, Cubit ๋“ฑ ์ง€์›
๊ธฐ๋ณธ์ ์œผ๋กœ ์ง€์› X (FutureBuilder ์‚ฌ์šฉํ•ด์•ผ ํ•จ)
FutureProvider, AsyncNotifier ์ œ๊ณต
์˜์กด์„ฑ ์ฃผ์ž… (DI)
Get.put(), Get.find()
RepositoryProvider, MultiBlocProvider
DI ๊ธฐ๋ณธ ์ง€์› ์—†์Œ (Provider ์ง์ ‘ ์ฃผ์ž…)
Provider ๊ธฐ๋ฐ˜ DI ์‚ฌ์šฉ (ref.read(), ref.watch())
๋ผ์šฐํŒ… ๊ด€๋ฆฌ
Get.to(), Get.off()
์—†์Œ
์—†์Œ
์—†์Œ
์ „์—ญ ์ƒํƒœ ๊ด€๋ฆฌ
Get.put()์œผ๋กœ ์‰ฝ๊ฒŒ ๊ฐ€๋Šฅ
๊ฐ€๋Šฅ (BlocProvider)
๊ฐ€๋Šฅ (MultiProvider)
ProviderScope ์‚ฌ์šฉ
๋ฐ˜์‘ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์ง€์›
๊ฐ€๋Šฅ (RxDart ์—†์ด๋„ ๋ฐ˜์‘ํ˜• ๊ฐ€๋Šฅ)
๊ฐ•๋ ฅํ•œ ์ด๋ฒคํŠธ ๊ธฐ๋ฐ˜
์ œํ•œ์ 
๊ฐ€๋Šฅ (watch(), listen())
์ฝ”๋“œ ๋ณต์žก๋„
์‰ฌ์›€ (๋ณด์ผ๋Ÿฌํ”Œ๋ ˆ์ดํŠธ ์ ์Œ)
๊ฐ€์žฅ ๋ณต์žกํ•จ
๋ณด์ผ๋Ÿฌํ”Œ๋ ˆ์ดํŠธ ๋งŽ์Œ
๋น„๊ต์  ๋ณต์žกํ•จ
์„ฑ๋Šฅ ์ตœ์ ํ™”
์šฐ์ˆ˜ (GetBuilder ์‚ฌ์šฉ ๊ฐ€๋Šฅ)
์šฐ์ˆ˜ (BlocListener, BlocObserver)
๋น„๊ต์  ๋‚ฎ์Œ
์šฐ์ˆ˜ (watch(), read())
๋ฉ”๋ชจ๋ฆฌ ํšจ์œจ์„ฑ
๋†’์€ ์„ฑ๋Šฅ (Get.lazyPut() ์ง€์›)
์ด๋ฒคํŠธ ๋‹จ์œ„๋กœ ์ƒํƒœ ์œ ์ง€
ํ•ญ์ƒ ์ธ์Šคํ„ด์Šค ์œ ์ง€
ํ•„์š”ํ•  ๋•Œ๋งŒ ์ดˆ๊ธฐํ™” (lazy initialization)
ํ…Œ์ŠคํŠธ ์šฉ์ด์„ฑ
์ƒ๋Œ€์ ์œผ๋กœ ๋ถ€์กฑ
๊ฐ€์žฅ ์šฐ์ˆ˜
๋น„๊ต์  ์‰ฌ์›€
๋งค์šฐ ์šฐ์ˆ˜
์•ฑ ํฌ๊ธฐ ์˜ํ–ฅ
๊ฐ€์žฅ ๊ฐ€๋ฒผ์›€
๊ฐ€์žฅ ๋ฌด๊ฑฐ์›€
์ƒ๋Œ€์ ์œผ๋กœ ๋ฌด๊ฑฐ์›€
๊ฐ€๋ฒผ์›€
Flutter ๊ณต์‹ ์ง€์›
๋น„๊ณต์‹
Flutter ํŒ€ ๊ณต์‹ ์ง€์›
๊ณต์‹ ํŒจํ‚ค์ง€
๊ณต์‹ ํŒจํ‚ค์ง€
๋Œ€๊ทœ๋ชจ ์•ฑ ์ ํ•ฉ์„ฑ
์ž‘์€ ์•ฑ์— ์ ํ•ฉ
๋Œ€๊ทœ๋ชจ ์•ฑ์— ๊ฐ€์žฅ ์ ํ•ฉ
๊ฐ€๋Šฅ
์ค‘ยท๋Œ€๊ทœ๋ชจ ์•ฑ ๊ฐ€๋Šฅ

Riverpod์„ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ

BuildContext ์—†์ด ์ „์—ญ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•˜๊ณ  ์‹ถ์„ ๋•Œ
Provider๋ณด๋‹ค ๋” ์•ˆ์ „ํ•œ ์ƒํƒœ ๊ด€๋ฆฌ๊ฐ€ ํ•„์š”ํ•  ๋•Œ
๋น„๋™๊ธฐ ์ƒํƒœ (API ์š”์ฒญ, DB ํ˜ธ์ถœ ๋“ฑ) ์ฒ˜๋ฆฌ๊ฐ€ ๋งŽ์„ ๋•Œ
์˜์กด์„ฑ ์ฃผ์ž…(DI)์„ ํšจ์œจ์ ์œผ๋กœ ๊ด€๋ฆฌํ•˜๊ณ  ์‹ถ์„ ๋•Œ
๊ฒฐ๋ก : Riverpod์€ ๊ฐ•๋ ฅํ•˜๊ณ  ์œ ์—ฐํ•œ ์ƒํƒœ๊ด€๋ฆฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ด๋ฉฐ, Provider๋ณด๋‹ค ๋” ๋‚˜์€ ๊ตฌ์กฐ๋ฅผ ์ œ๊ณตํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋Œ€๊ทœ๋ชจ ํ”„๋กœ์ ํŠธ์—์„œ๋„ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค!