Flutter

Flutter – Riverpod

Riverpod에서 사용되는 다양한 Provider: 개요와 사용법

Riverpod은 Flutter/Dart 애플리케이션에서 상태 관리를 쉽게 할 수 있도록 도와주는 강력한 패키지입니다. 특히 다양한 비즈니스 로직에 맞게 사용할 수 있는 여러 가지 Provider가 제공되며, 각각의 특징과 사용 방법을 이해하는 것이 중요합니다. 이 글에서는 NotifierProvider, AsyncNotifierProvider, StreamNotifierProvider, ChangeNotifierProvider와 같은 Riverpod의 주요 Provider들을 주제별로 나누어 설명합니다.


1. NotifierProvider: 동기적 상태 관리를 위한 기본 제공자

개요

NotifierProviderNotifier 클래스를 상속받은 하위 클래스를 노출하고 구독할 수 있도록 해줍니다. 이 Provider는 복잡한 비즈니스 로직을 처리하는 데 적합하며, 상태 변경은 반드시 Notifier의 인터페이스를 통해서만 이루어지도록 제한하여 안전한 상태 관리를 보장합니다.

특징

  • 복잡한 비즈니스 로직 처리: 상태 변경을 인터페이스를 통해서만 가능하게 하여 명확한 코드 흐름 유지.
  • 동기적 상태 초기화: 상태는 동기적으로 초기화됩니다.
  • 권장 사용 방식: 최신 Riverpod 애플리케이션에서 복잡한 동기적 상태 관리가 필요할 때 NotifierProvider가 권장됩니다.
  • 코드 생성 지원: riverpod_generator를 통해 코드 생성을 지원합니다.

사용 예

final myNotifierProvider = NotifierProvider<MyNotifier, MyState>((ref) {
  return MyNotifier();
});

2. AsyncNotifierProvider: 비동기적 상태 관리를 위한 최적의 선택

개요

AsyncNotifierProviderAsyncNotifier를 기반으로 한 프로바이더로, 비동기 상태 관리를 필요로 할 때 사용됩니다. 이 Provider는 상태를 비동기적으로 초기화하고 변경할 수 있는 기능을 제공합니다.

특징

  • 비동기적 상태 관리: AsyncNotifier는 상태를 비동기적으로 초기화할 수 있습니다.
  • 복잡한 비즈니스 로직 처리: 비동기 작업이 포함된 복잡한 상태 관리가 필요할 때 적합.
  • 권장 사용 방식: 비동기 작업을 수반하는 상태 관리가 필요할 때 강력히 추천됩니다.

사용 예

final myAsyncNotifierProvider = AsyncNotifierProvider<MyAsyncNotifier, AsyncValue<MyState>>((ref) {
  return MyAsyncNotifier();
});

3. StreamNotifierProvider: 실시간 데이터 스트리밍을 위한 선택

개요

StreamNotifierProviderStreamNotifier를 기반으로 한 프로바이더로, stream을 사용하여 실시간으로 상태를 업데이트할 수 있습니다. 비동기 데이터를 계속해서 수신해야 하는 경우에 적합합니다.

특징

  • Stream을 통한 상태 업데이트: StreamNotifierbuild 메서드 내에서 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의 프로바이더는 상태의 라이프사이클을 통해 관리됩니다.

라이프사이클 단계

  1. Uninitialized/Disposed:
  • 프로바이더에 자원이 할당되지 않은 상태입니다.
  • 프로바이더가 초기화되지 않았거나, 해제된 경우입니다.
  1. Alive:
  • build 함수가 실행되고, 프로바이더의 상태가 ProviderScope에 저장된 상태입니다.
  • 위젯이나 다른 프로바이더로부터 watch/listen을 통해 프로바이더의 상태가 구독되고 있을 때 해당됩니다.
  1. Paused:
  • 더 이상 프로바이더를 구독하는 리스너가 없는 상태입니다.
  • 이후 watch/listen이 재개되면 다시 Alive 상태로 돌아갑니다.
  1. Disposed:
  • 프로바이더가 다시 생성되거나 수동으로 무효화되었을 때 해당됩니다.
  • 더 이상 자원이 할당되지 않으며, 상태는 초기화됩니다.

라이프사이클 메서드

  1. onAddListener(void cb()):
  • 프로바이더에 새 리스너가 추가될 때 호출됩니다.
  1. onRemoveListener(void cb()):
  • 프로바이더에서 리스너가 제거될 때 호출됩니다.
  1. onCancel(void cb()):
  • 프로바이더의 마지막 리스너가 제거될 때 호출됩니다.
  1. onResume(void cb()):
  • Paused 상태의 프로바이더에 리스너가 다시 추가될 때 호출됩니다.
  1. onDispose(void cb()):
  • 프로바이더가 파괴되기 직전에 호출됩니다.

라이프사이클 관리

  • 프로바이더의 상태는 필요에 따라 초기화되고 해제됩니다.
  • autoDispose를 사용하면 더 이상 필요하지 않은 프로바이더를 자동으로 해제하여 메모리 자원을 효율적으로 관리할 수 있습니다.

결론

Riverpod은 다양한 Provider를 통해 복잡한 상태 관리 문제를 쉽게 해결할 수 있는 강력한 도구입니다. NotifierProviderAsyncNotifierProvider는 최신 애플리케이션 개발에서 복잡한 동기 및 비동기 상태 관리를 처리할 때 매우 유용합니다. StreamNotifierProvider는 실시간 데이터 처리가 필요한 경우에 적합하며, ChangeNotifierProvider는 간단한 상태 관리에 사용할 수 있으나 최신 Riverpod 패턴에서는 더 이상 권장되지 않습니다.

상황에 맞는 Provider를 선택하여 애플리케이션의 상태 관리를 더 쉽게 하고, 복잡한 비즈니스 로직을 처리할 수 있습니다.