Flutter

Riverpod 공식문서 읽어보기 (1) Make your first provider/network request

flutter developer 2025. 3. 10. 11:26

https://riverpod.dev/docs/essentials/first_request

Make your first provider/network request | Riverpod

Network requests are the core of any application. But there are a lot of things to consider when

riverpod.dev


1. 리버팟으로 네트워크 요청하기 - Make your first provider/network request

1-1. Riverpod을 사용하려면 앱 최상단에 ProviderScope를 추가해야한다. - Setting up ProviderScope

ProviderScope는 Riverpod의 상태 저장소 역할을 한다. 즉 각 Provider의 상태를 중앙에서 관리하고 캐싱하는 인프라같다고 볼 수 있다. 만약 providerScope가 없다면 위젯이 리빌드 될 때마다 Provider를 통해 API를 재요청하게 된다. (물론 애초에 에러나서 이럴일은 없다)
 
공식문서를 읽으면서 ProviderScope가 마치 DI Container 와 비슷하다는 인상을 받았다. Provider Scope에 Provider를 등록하면 특정 메모리 주소에 provider 상태를 넣은 후 이 주소를 나중에 재사용해서 쓰기 때문이다. 
 
공식문서에서는 Provider에 대해 4가지 특징을 설명하고 있다.
 
(1) 캐싱기능
네트워크 요청을 매번 실행하는 것이 아닌 한 번 실행 후 캐싱하여 재사용

(2) 로딩/에러 처리 기능 
RiverPod의 AsyncValue를 사용하면 Loading, Data, Error 상태를 자동으로 관리
 
(3) 리스너 기능 
UI에서 ref.watch(provider)를 사용하면 Provider값이 변경될 때 자동으로 UI가 업데이트 되어 데이터 변경을 쉽게 추적할 수 있음
 
(4) 데이터 변경시 자동으로 재실행
Provdier가 의존하는 데이터가 변경되면 자동으로 다시 실행된다.
 

1-2. 모델 정의 - Defining the model

네트워크 요청으로 받은 JSON데이터를 다트 객체로 변환하기 위해 Freezed or Json_Serializable 패키지를 써서 모델을 선언한다.
 

1-3.  Provider 만들기 - Creating the provider

@riverpod 어노테이션을 사용하면 코드젠을 통해 Provider를 생성시켜준다. 파라미터로는 Ref 타입을 받는 것을 확인할 수 있다. Ref는 네이밍 그대로 provider를 참조(reference)해서 내부 상태를 (메서드를 통해) 조작하는 것이다. activity 함수의 경우 Ref타입을 받고있는데 이는 다른 Provider를 가져와서 실핼하는 일종의 provider간 상호작용을 위한 것으로 써놓은 예제이다.
 

1-4.  UI에서 Provider 사용  - Rendering the network request's reponse in the UI

네트워크 요청을 UI에서 처리하려면 Consumer 혹은 ConsumerWidget을 사용해야한다.ref.watch 를 사용해 네트워크 요청을 수행후 결과값을 switch 로 data, error, _(로딩상태)를 분기처리해준다. 이때 ref 주요 메서드인 watch, listen, read의 차이는 아래와 같다. 

ref.watch: 값이 변할 때마다 위젯을 재빌드.


ref.listen: 값이 변할 때마다 콜백 함수를 실행하지만, 위젯 재빌드는 하지 않음.


ref.read: 값을 읽지만, 후속 변경을 추적하지 않음.

 

출처: https://white-developer.tistory.com/146

 
후술할 ConsumerWidger의 차이이기도 한데 만약 이런식으로 Consumer를 리턴할 경우 Provider의 상태가 변할 때 Consumer내부 위젯만 리빌드되고 Scaffold 같은 부모 위젯은 그대로 유지된다. 즉 성능 최적화를 해야한다! 할 때 쓸 수 있다.
 

ConsumeWidget을 사용할 경우 Consumer로 위젯을 따로 감쌀 필요없이 Build메서드 안에서 위젯을 선언하면된다. Consumer로 따로 감쌀 필요없이 ref를 바로 사용할 수 있어 코드가 깔끔해지지만 Provider 상태변화시 위젯 전체가 리빌드된다.

ConsumerWidget과 ConsumerStatefulWidget의 가장 큰차이는 라이프사이클 함수에서 ref를 사용할 수 있느냐이다. 둘 중 어느것을 선택해야하나! 라고 물어본다면 사실상 리버팟으로 상태관리할 때 StatlessWidget을 쓸까 StatefulWidget을 쓸까 라는 고민과 거의 비슷하다 -> 언제 StatlessWidget을 쓰는지, 언제 StatefulWidget을 쓰는지는 이곳에 정리해두었다 :) 
 

1-5.  Flutter Hook 사용해보기 - Combining HookWidget and ConsumerWidget

https://medium.com/flutter-community/stateful-widgets-145d6d43af67

먼저 Flutter Hook이란 무엇인지 알아보자. 기존 StatefulWidget을 사용하기 위해서는 보일러플레이트 코드가 너무 많았다.
 

https://gist.github.com/suojae/8218c7c9e21ecd95c1517ddebcad4751

Flutter Hook을 사용하면 State 클래스를 따로 선언할 필요도 없고 그에따라 createState같은 메서드도 축약할 수 있게 된다. 단지 useState 메서드를 통해 상태를 관리하게 된다.
 

이러한 flutter hook은 리버팟과 함께 사용할 수 있는데 HookConsumerWidget 을 사용하면 useState() 같은 Hook을 사용하면서도 ref.watch() 사용할 수 있어 코드를 간결하게 가져갈 수 있다. 
 
개인적으로 확실히 StatefulWidget에서 hook을 사용하면 코드가 간결해지는건 알겠는데 리버팟+hook까지 사용하면 너무 서드파티에 의존하게 되는 것 같아서 굳이..? 라는 생각이 들긴한다.