Riverpod에서 사용되는 다양한 Provider: 개요와 사용법
Riverpod은 Flutter/Dart 애플리케이션에서 상태 관리를 쉽게 할 수 있도록 도와주는 강력한 패키지입니다. 특히 다양한 비즈니스 로직에 맞게 사용할 수 있는 여러 가지 Provider가 제공되며, 각각의 특징과 사용 방법을 이해하는 것이 중요합니다. 이 글에서는 NotifierProvider, AsyncNotifierProvider, StreamNotifierProvider, ChangeNotifierProvider와 같은 Riverpod의 주요 Provider들을 주제별로 나누어 설명합니다.
1. NotifierProvider: 동기적 상태 관리를 위한 기본 제공자
개요
NotifierProvider
는 Notifier
클래스를 상속받은 하위 클래스를 노출하고 구독할 수 있도록 해줍니다. 이 Provider는 복잡한 비즈니스 로직을 처리하는 데 적합하며, 상태 변경은 반드시 Notifier의 인터페이스를 통해서만 이루어지도록 제한하여 안전한 상태 관리를 보장합니다.
특징
- 복잡한 비즈니스 로직 처리: 상태 변경을 인터페이스를 통해서만 가능하게 하여 명확한 코드 흐름 유지.
- 동기적 상태 초기화: 상태는 동기적으로 초기화됩니다.
- 권장 사용 방식: 최신 Riverpod 애플리케이션에서 복잡한 동기적 상태 관리가 필요할 때
NotifierProvider
가 권장됩니다. - 코드 생성 지원:
riverpod_generator
를 통해 코드 생성을 지원합니다.
사용 예
final myNotifierProvider = NotifierProvider<MyNotifier, MyState>((ref) {
return MyNotifier();
});
2. AsyncNotifierProvider: 비동기적 상태 관리를 위한 최적의 선택
개요
AsyncNotifierProvider
는 AsyncNotifier
를 기반으로 한 프로바이더로, 비동기 상태 관리를 필요로 할 때 사용됩니다. 이 Provider는 상태를 비동기적으로 초기화하고 변경할 수 있는 기능을 제공합니다.
특징
- 비동기적 상태 관리:
AsyncNotifier
는 상태를 비동기적으로 초기화할 수 있습니다. - 복잡한 비즈니스 로직 처리: 비동기 작업이 포함된 복잡한 상태 관리가 필요할 때 적합.
- 권장 사용 방식: 비동기 작업을 수반하는 상태 관리가 필요할 때 강력히 추천됩니다.
사용 예
final myAsyncNotifierProvider = AsyncNotifierProvider<MyAsyncNotifier, AsyncValue<MyState>>((ref) {
return MyAsyncNotifier();
});
3. StreamNotifierProvider: 실시간 데이터 스트리밍을 위한 선택
개요
StreamNotifierProvider
는 StreamNotifier
를 기반으로 한 프로바이더로, stream을 사용하여 실시간으로 상태를 업데이트할 수 있습니다. 비동기 데이터를 계속해서 수신해야 하는 경우에 적합합니다.
특징
- Stream을 통한 상태 업데이트:
StreamNotifier
는build
메서드 내에서 stream을 생성하고, 이를 통해 지속적으로 상태를 업데이트할 수 있습니다. - 복잡한 상태 처리: 비동기 상태 뿐만 아니라 지속적으로 업데이트되는 상태를 처리할 때 유용합니다.
- 수정자 지원:
autoDispose
,family
등의 수정자를 통해 다양한 상황에서 유연하게 사용 가능합니다.
사용 예
final myStreamNotifierProvider = StreamNotifierProvider<MyStreamNotifier, AsyncValue<MyState>>((ref) {
return MyStreamNotifier();
});
4. ChangeNotifierProvider: 간단한 상태 관리를 위한 제공자 (권장되지 않음)
개요
ChangeNotifierProvider
는 Flutter에서 제공하는 ChangeNotifier
클래스를 기반으로 상태를 관리하는 프로바이더입니다. 간단한 상태 관리나 단일 위젯 간 상태 공유에 적합하지만, Riverpod의 최신 패턴에서는 권장되지 않습니다.
특징
- 외부에서 상태 변경 가능:
ChangeNotifierProvider
는 외부에서 직접 상태를 변경할 수 있습니다. - 권장되지 않음: 상태 관리를 더 엄격하게 제어할 수 있는
NotifierProvider
와 같은 대안이 권장됩니다. - 코드 생성 지원 안 됨: 자동화된 코드 생성이 지원되지 않으므로, 큰 프로젝트에서 관리가 어려울 수 있습니다.
사용 예
final myChangeNotifierProvider = ChangeNotifierProvider<MyChangeNotifier>((ref) {
return MyChangeNotifier();
});
5. invalidate와 refresh: 프로바이더 상태 제어
Riverpod에서는 프로바이더의 상태를 무효화하거나 다시 계산할 수 있는 메서드를 제공합니다.
invalidate
:
- 상태를 무효화하여 다음 읽기 시 상태가 갱신되도록 합니다. 즉시 갱신되지 않으며, 다음 프레임에서 갱신됩니다.
- 여러 번 호출해도 한 번만 갱신됩니다.
refresh
:
- 프로바이더의 상태를 즉시 다시 계산하고, 그 결과값을 반환합니다.
- 상태를 즉시 다시 가져와야 하는 상황에서 유용합니다.
사용 예
final newValue = ref.refresh(myProvider); // 즉시 다시 계산
ref.invalidate(myProvider); // 다음 프레임에서 갱신
6. Riverpod의 라이프사이클
Riverpod의 프로바이더는 상태의 라이프사이클을 통해 관리됩니다.
라이프사이클 단계
- Uninitialized/Disposed:
- 프로바이더에 자원이 할당되지 않은 상태입니다.
- 프로바이더가 초기화되지 않았거나, 해제된 경우입니다.
- Alive:
- build 함수가 실행되고, 프로바이더의 상태가 ProviderScope에 저장된 상태입니다.
- 위젯이나 다른 프로바이더로부터 watch/listen을 통해 프로바이더의 상태가 구독되고 있을 때 해당됩니다.
- Paused:
- 더 이상 프로바이더를 구독하는 리스너가 없는 상태입니다.
- 이후 watch/listen이 재개되면 다시
Alive
상태로 돌아갑니다.
- Disposed:
- 프로바이더가 다시 생성되거나 수동으로 무효화되었을 때 해당됩니다.
- 더 이상 자원이 할당되지 않으며, 상태는 초기화됩니다.
라이프사이클 메서드
- onAddListener(void cb()):
- 프로바이더에 새 리스너가 추가될 때 호출됩니다.
- onRemoveListener(void cb()):
- 프로바이더에서 리스너가 제거될 때 호출됩니다.
- onCancel(void cb()):
- 프로바이더의 마지막 리스너가 제거될 때 호출됩니다.
- onResume(void cb()):
- Paused 상태의 프로바이더에 리스너가 다시 추가될 때 호출됩니다.
- onDispose(void cb()):
- 프로바이더가 파괴되기 직전에 호출됩니다.
라이프사이클 관리
- 프로바이더의 상태는 필요에 따라 초기화되고 해제됩니다.
- autoDispose를 사용하면 더 이상 필요하지 않은 프로바이더를 자동으로 해제하여 메모리 자원을 효율적으로 관리할 수 있습니다.
결론
Riverpod은 다양한 Provider를 통해 복잡한 상태 관리 문제를 쉽게 해결할 수 있는 강력한 도구입니다. NotifierProvider와 AsyncNotifierProvider는 최신 애플리케이션 개발에서 복잡한 동기 및 비동기 상태 관리를 처리할 때 매우 유용합니다. StreamNotifierProvider는 실시간 데이터 처리가 필요한 경우에 적합하며, ChangeNotifierProvider는 간단한 상태 관리에 사용할 수 있으나 최신 Riverpod 패턴에서는 더 이상 권장되지 않습니다.
상황에 맞는 Provider를 선택하여 애플리케이션의 상태 관리를 더 쉽게 하고, 복잡한 비즈니스 로직을 처리할 수 있습니다.