Riverpod?
Riverpod은 상태관리 라이브러리로, Provider의 단점을 보완한 것이라고 생각하면 된다.
Riverpod은 어디서든 변경을 감지하는 상태관리 라이브러리이다. 어디서든 상태값에 접근이 가능하고, 결합해 사용도 가능하다. 또한, 로드/오류 이슈를 처리할 수 있다는 점이 매력적이다.
그렇다면 상태관리란 무엇일까?
상태관리
Flutter의 상태 관리란, 쉽게 생각해서 데이터의 상태이다. 현재 데이터에 맞게 화면을 변경해주고 유저의 반응에 대응해주기 위해 필요하다. 하지만 모든 데이터를 관리해야 하는 것은 아니다. 어떤 상태냐에 따라 Ephemeral(일시적)state, App state로 나뉘게 된다.
Ephemeral state?
Ephemeral state는 임시적인 상태라는 뜻이다. Local state와 의미가 비슷하다. '한 개의 위젯이 가지는 상태'를 Ephemeral state라고 한다.
예를 들면 아래와 같다.
위와 같은 경우에는 상태 관리법을 사용할 필요 없다. 현재 페이지에서만 사용하는 상태이면서 다른 곳에 영향을 주지 않는 경우(Local)를 말한다. 이런 경우에는 상태 관리가 별로 필요없다.
하지만 앱 전체에 영향을 준다면 상태 관리를 할 필요가 있다.
App state
App state는 어떤 상태가 앱 전체에 영향을 주는 경우를 말한다.
예를 들면 아래와 같다.
위와 같은 경우에는 앱 전체에 영향을 주기 때문에 App state라고 한다. 간혹 shared state라고도 한다.
위에 말한 Ephemeral state와 App state를 구분하는 명확한 기준은 없다. 개발 처음에는 Ephemeral state라고 생각했지만, 리팩토링을 거치며 App state로 변하는 경우도 많다.
App state를 관리하는 것을 state management라고 하는데, 상태 관리법이다. 그리고 이 글에서는 상태관리법 중 Riverpod에 대해서 알아보고자 한다.
Riverpod vs Provider
Riverpod은 Provider의 단점을 개선한 버전이다. 우선 Riverpod 공식 사이트에서 말하는 장점을 살펴보면 아래와 같다.
많은 개발자들이 Riverpod을 사용하고 있다.
Riverpod의 Provider 종류
Provider
StateProvider
StateNotifierProvider
FutureProvider
StreamProvider
ChangeNotifierProvider
※ 각각 다른 타입을 반환해주고 사용 목적이 다르다
※ 모든 Provider는 글로벌하게 선언된다.
Provider
가장 기본 베이스가 되는 Provider
아무 타입이나 반환 가능
Service, 계산한 값 등을 반환할 때 사용
반환값을 캐싱할 때 유용하게 사용
-> 빌드 횟수 최소화 가능
여러 Provider의 값들을 묶어서 한번에 반환값을 만들어 낼 수 있다.
※ Provider 안에 Provider를 넣을 수 있음
StateProvider
UI에서 '직접적으로' 데이터를 변경할 수 있도록 하고 싶을 때 사용
단순한 형태의 데이터만 관리(int, double, String 등)
-> class 등의 형태는 다루지 않음
Map, List 등 복잡한 형태의 데이터는 다루지 않는다.
-> 다뤄도 상관은 없으나 잘 다루지 않음
복잡한 로직이 필요한 경우 사용하지 않는다.
-> number++ 정도의 간단한 로직으로만 한정
StateNotifierProvider
StateProvider와 마찬가지로 UI에서 '직접적으로' 데이터를 변경할 수 있도록 하고싶을 때 사용
복잡한 형태의 데이터 관리가능(클래스의 메소드를 이요한 상태관리)
StateNotifier를 상속한 클래스 반환
FutureProvider
Future 타입만 반환가능
API 요청의 결과를 반환할 때 자주 사용
복잡한 로직 또는 사용자의 특정 행동 뒤에 Future를 재실행하는 기능이 없음
-> 1회성 실행(단점)
-> 반복이 필요할 경우 StateNotifierProvider 사용
StreamProvider
Stream 타입만 반환가능
API 요청의 결과를 Stream으로 반환할 때 자주 사용
-> Socket 등
ref.read vs ref.watch
ref.watch는 반환값의 업데이트가 있을때 지속적으로 build 함수를 다시 실행해준다.
ref.watch는 필수적으로 UI관련 코드에만 사용
ref.read는 실행되는 순간 단 한번만 provider 값을 가져온다.
ref.read는 onPressed 콜백처럼 특정 액션 뒤에 실행되는 함수 내부에서 사용