반응형
6. Riverpod — 현대적인 의존성 주입 + 상태관리
Riverpod은 Provider의 한계를 극복한 차세대 상태관리입니다.
모든 Provider가 전역적으로 안전하며, 의존 관계 추적과 테스트가 용이합니다.
Riverpod 예제
import 'package:flutter_riverpod/flutter_riverpod.dart';
// 단순 Provider
final greetingProvider = Provider<String>((ref) => 'Hello Riverpod');
// 상태 변경 가능한 Provider
class Counter extends Notifier<int> {
@override
int build() => 0;
void increment() => state++;
}
final counterProvider = NotifierProvider<Counter, int>(Counter.new);
ConsumerWidget 사용 예시
class CounterPage extends ConsumerWidget {
const CounterPage({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final count = ref.watch(counterProvider);
return Scaffold(
body: Center(child: Text('$count')),
floatingActionButton: FloatingActionButton(
onPressed: () => ref.read(counterProvider.notifier).increment(),
child: const Icon(Icons.add),
),
);
}
}
테스트가 쉬운 이유
void main() {
test('Counter increments', () {
final container = ProviderContainer();
final counter = container.read(counterProvider.notifier);
counter.increment();
expect(container.read(counterProvider), 1);
});
}
✅ 요약: 전역 안전, autoDispose, 의존 추적, 테스트 친화적
7. BLoC / Cubit — 이벤트 기반 리액티브 아키텍처
BLoC(Business Logic Component)은 Event → State 흐름으로 동작합니다.
Cubit은 BLoC의 경량 버전으로 보일러플레이트가 적습니다.
Cubit 예시
class CounterCubit extends Cubit<int> {
CounterCubit() : super(0);
void increment() => emit(state + 1);
}
class CounterView extends StatelessWidget {
const CounterView({super.key});
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (_) => CounterCubit(),
child: Scaffold(
body: Center(
child: BlocBuilder<CounterCubit, int>(
builder: (_, count) => Text('$count'),
),
),
floatingActionButton: FloatingActionButton(
onPressed: () => context.read<CounterCubit>().increment(),
child: const Icon(Icons.add),
),
),
);
}
}
BLoC (이벤트 → 상태)
sealed class TodoEvent {}
class FetchTodos extends TodoEvent {}
class AddTodo extends TodoEvent { AddTodo(this.title); final String title; }
sealed class TodoState {}
class TodoLoading extends TodoState {}
class TodoLoaded extends TodoState { TodoLoaded(this.items); final List<Todo> items; }
class TodoError extends TodoState { TodoError(this.message); final String message; }
class TodoBloc extends Bloc<TodoEvent, TodoState> {
final TodoRepository repo;
TodoBloc(this.repo): super(TodoLoading()) {
on<FetchTodos>((event, emit) async {
try {
final items = await repo.fetchTodos();
emit(TodoLoaded(items));
} catch (e) {
emit(TodoError(e.toString()));
}
});
}
}
BLoC 장점
- 예측 가능하고 유지보수 쉬움
- 복잡한 비즈니스 로직에 적합
- 강력한 로깅/디버깅/QA 지원
8. GetX — 빠르고 간단한 올인원 프레임워크
GetX는 상태관리 + 라우팅 + 의존성 주입을 통합 제공합니다.
예제
class CounterController extends GetxController {
final count = 0.obs;
void increment() => count.value++;
}
class CounterPage extends StatelessWidget {
const CounterPage({super.key});
@override
Widget build(BuildContext context) {
final controller = Get.put(CounterController());
return Scaffold(
body: Center(child: Obx(() => Text('${controller.count}'))),
floatingActionButton: FloatingActionButton(
onPressed: controller.increment,
child: const Icon(Icons.add),
),
);
}
}
장점
- 코드 간결, 러닝커브 낮음
- 라우팅/DI 내장
단점
- 전역 남용 시 결합도 증가
- 대형 프로젝트엔 구조화 필요
⚠️ 권장 사용법:
GetX Controller에는 UI 로직만 두고, 비즈니스 로직은 UseCase나 Repository로 분리하세요.
9. 중간 비교 요약
항목RiverpodBLoCGetX
| 설계 철학 | 안전한 DI 기반 | 이벤트 리액티브 | 올인원 솔루션 |
| 러닝커브 | 중간 | 높음 | 낮음 |
| 코드 복잡도 | 중 | 높음 | 낮음 |
| 테스트 용이성 | 매우 높음 | 높음 | 낮음 |
| 전역 안전성 | 높음 | 높음 | 낮음 |
| 추천 규모 | 중~대형 | 대형 | 소~중형 |
반응형
'Dev Study > Flutter & Dart' 카테고리의 다른 글
| Flutter 게임 개발 라이브러리 용도별 장단점 (2025 기준) (0) | 2025.11.06 |
|---|---|
| Flutter 클린 아키텍처에 어울리는 상태관리 가이드 (0) | 2025.11.05 |
| Flutter 상태관리 완전 가이드 (Part 3/3) (0) | 2025.11.05 |
| Flutter 상태관리 완전 가이드 (Part 1/3) (0) | 2025.11.05 |
| Flutter 빌드는 되는데 실행할때 오류나는 경우 (0) | 2025.11.04 |
| Dart 상위 위젯과 하위 위젯의 상태값 가져오기 (0) | 2023.11.20 |
| Dart 상속 (0) | 2023.11.17 |
| Dart Class 생성자 (0) | 2023.11.17 |

