flutter riverpod

koonlx·2025년 6월 4일

riverpod

목록 보기
1/4
post-thumbnail

Flutter를 처음 접하여 riverpod를 사용중인데 아직 익숙하지 않아서 쉽게 이해해보고자 작성하는 글이다.

Provider가 상태를 관리한다?
Consumer는 Provider에서 상태를 가져다 쓴다?
Notifier는 비즈니스 로직(상태 변경)을 실행하는 건가?
ref는 대체 뭐하는 역할이지?

해당 글에서는 provider와 riverpod의 핵심 개념을 간략하게 이해하는 것이 목표다.

1. 핵심 요약

  • Provider
    상태 또는 객체(서비스, 값 등)를 외부에 공급하는 역할
  • Consumer
    Provider에서 공급된 상태(값)를 구독하여, UI/로직을 자동 업데이트하는 역할
  • Notifier
    상태의 변경이나 비즈니스 로직(상태 전이)을 담당하는 역할
  • ref
    Provider, 상태, 의존성(서비스 등)에 접근하는 열쇠(key)이자 연결자

2. 개념별 심화 분석

2-1. Provider

값, 객체, 서비스, 상태 등 공급(Provide)의 책임만을 지닌다.
상태를 "직접" 변경하진 않으며, 보통은 불변 객체/싱글턴/서비스 DI 용도로 많이 쓰인다.

  • 주요 역할
    외부에서 필요한 값/객체를 주입(Dependency Injection)
    상태 “생성”과 “공급” 담당
  • 예시 코드
final userProvider = Provider<User>((ref) => User(...));
  • 대표 Provider 종류
    Provider, StateProvider, FutureProvider, StreamProvider, StateNotifierProvider, AsyncNotifierProvider 등

2-2. Notifier (StateNotifier, AsyncNotifier 등)

실제 상태의 변경 및 비즈니스 로직을 담당
값의 set/update, API 통신, 복잡한 상태 변환 등 모든 변화의 주체
상태가 바뀌면 자동으로 구독 중인 Consumer/UI가 업데이트 된다.

  • 예시 코드
class CounterNotifier extends StateNotifier<int> {
  CounterNotifier() : super(0);
  void increment() => state++;
}
final counterProvider = StateNotifierProvider<CounterNotifier, int>((ref) => CounterNotifier());

2-3. Consumer

Provider에서 공급한 상태(값)의 변화를 감지해서
필요에 따라 UI나 로직을 자동으로 리빌드하는 구독자

  • 예시 코드
Consumer(
  builder: (context, ref, child) {
    final value = ref.watch(counterProvider);
    return Text('$value');
  }
)

2-4. ref

Provider/상태/서비스에 접근하는 열쇠이자 연결자(핸들러)
역할
Provider 내부/외부에서 다른 Provider, 상태, 의존성에 접근
read, watch, listen 등 다양한 메서드 제공
상태를 읽고(ref.read), 구독(ref.watch), 변화 감지(ref.listen)

  • 공식적 설명
    “Riverpod 생태계에서 상태, 의존성, 서비스를 안전하게 연결/접근/조작하게 해주는 핵심 핸들러”
  • 예시 코드
// Provider에서 값 읽기
final count = ref.watch(counterProvider);

// Notifier에서 서비스 객체 불러오기
final api = ref.read(apiProvider);

3. 공식 예제 한눈에 보기

// Provider
final userProvider = Provider<User>((ref) => User(...));

// Notifier
class CounterNotifier extends StateNotifier<int> { ... }
final counterProvider = StateNotifierProvider<CounterNotifier, int>((ref) => CounterNotifier());

// Consumer
Consumer(
  builder: (context, ref, child) {
    final value = ref.watch(counterProvider);
    return Text('$value');
  }
);

// ref 사용법
final count = ref.watch(counterProvider); // 상태 구독
final api = ref.read(apiProvider); // Provider로부터 서비스 객체 읽기

4. 실전 베스트 프랙티스/팁

단순한 값, DI만 필요하면 Provider
상태 변경(증가/감소/비동기 등)이 필요하면 Notifier
변화에 따라 UI 자동 변경이 필요하면 Consumer
모든 Provider/Notifier/서비스 연결은 ref를 사용

5. 한 번 더 정리

Provider:
“상태/객체의 외부 공급자”
Notifier:
“상태 및 비즈니스 로직(변경) 관리자”
Consumer:
“상태 구독자/변화 반응자”
ref:
“상태, 서비스, 의존성을 안전하게 연결/조작하는 핵심 열쇠”

프론트 개발에서 상태관리는 react hook만 써봐서 잘 모르지만 상태관리도구로 DI를 적극적으로 지원하는 경우는 없을거라고 막연히 생각했었다.(이름 그대로 상태를 관리하기 위한 도구이다보니..) 하지만 riverpod는 DI를 적극적으로 지원한다는 느낌을 받았다. Spring에서의 bean역할을 상태관리도구로 구현가능한 느낌이라서 신선하면서도 적용함에 부담이 없었다.

flutter 환경이 아직 많이 낯설지만 다른 프레임워크 또는 라이브러리의 개념과 비교하고 대조하면서 개념을 흡수하니 꽤 익숙해지고 있다. 기존에 알고있던 개념들을 다른 관점으로 활용하는 것을 보니 재미도 있다.

profile
Server Developer

0개의 댓글