플러터 상태관리 패키지 - Riverpod

가으라늘·2022년 4월 25일
0
post-thumbnail

플러터 상태관리 패키지를 선택해야 하는데, 실무에선 provider 패키지를 사용했었다. 그런데 이 provider를 개선한 새로운 패키지가 나왔다고 한다. riverpod이다. riverpod은 공식 문서까지 있다.

Riverpod 리엑티싱 캐싱, 데이터바인딩 프레임워크

공식 문서에 들어가보니 riverpod은 패키지가 여러 종류로 나뉘어져 있다고 한다. 기본 패키지인 flutter_riverpod, flutter_hooks를 같이 사용하는 hooks_riverpod, 그리고 플러터를 사용하지 않는 riverpod. 당연히 나는 플러터와 함께 사용할 것이기에 flutter_riverpod을 설치할 것이다.
패키지를 설치한 이후, 나오는 예제 코드를 그대로 따라했다. 하라는 대로 하고 실행하니 화면에 'Hello World'라고 나온다. 일단 여기까지 한 소감으로는, 여전히 모르겠다!

그래서 이번엔 Counter 예제를 따라했다. 일단 provider 폴더를 따로 만들어서 counter_provider.dart 파일을 만든 후 다음과 같이 코드를 작성했다.

import 'package:flutter_riverpod/flutter_riverpod.dart';

final counterProvider = StateProvider((ref) => 0);

그러고 나서 main.dart에 다음과 같이 작성하였다.

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_windows/provider/counter_provider.dart';

void main() {
  runApp(
    const ProviderScope(
      child: MyApp(),
    ),
  );
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(home: Home());
  }
}

class Home extends ConsumerWidget {
  const Home({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Counter Example'),
      ),
      body: Center(
        child: Consumer(builder: (context, ref, _) {
          final int count = ref.watch(counterProvider.state).state;
          return Text('$count');
        }),
      ),
      floatingActionButton: FloatingActionButton(
        // read 메서드는 provider를 listen하지 않고 읽을 수 있게 해준다.
        onPressed: () => ref.watch(counterProvider.state).state++,
        child: const Icon(Icons.add),
      ),
    );
  }
}

원래 FloatingActionButton 안에는 ref.read 메서드를 사용했다. 그런데 공식 문서에선 ref.read나 ref.listen보다 ref.watch를 사용할 것을 권장한다고 한다. ref.watch 사용 시 리액티브와 선언형에 가까워지고 유지보수하기 편해진다고 나온다. 그러면 사실 read나 listen은 사용 안 하고 watch만 사용하면 되는거 아닌가 생각했는데, 비동기처리 시에는 watch 메서드를 사용하지 말라고 한다. 이 때는 ref.read를 대신 사용하라고 한다.
ref.listen은 프로바이더를 관찰한다는 점에서 ref.watch와 유사하나, 두 메서드의 차이는, ref.watch가 프로바이더 상태값이 변경되면 widget/provider를 다시 빌드하지만 ref.listen은 함수를 호출한다는 차이가 있다고 한다. 즉, 화면을 다시 그릴 필요가 있으면 ref.watch를 사용하고, 그게 아니라 특정 함수만 호출하고 싶으면 listen을 사용하라는 얘기인데... 이건 직접 써보면서 감을 익혀야할 것 같다.

공식 문서에 나온 얘기들을 나열하자면,
ref.watch => 프로바이더의 값을 취득하고 변화를 구독한다. 값의 변경이 발생하면, 위젯을 다시 빌드하거나 값을 구독하고 있는 위치에 상태 값을 전달 및 제공한다. 다만, 비동기처리에 호출하면 안 된다. 이 때는 ref.read를 사용하도록 한다.
ref.listen => 프로바이더의 상태 값을 구독하거나 상태값이 변했을 때 어떠한 행위를 취해야할 경우 사용한다. watch와 마찬가지로 비동기처리에 호출하면 안 된다.
ref.read => 프로바이더의 상태값을 취득한다. 이벤트 콜백함수에 사용하기 유용하다. 일반적으로는 ref.watch를 사용하나, 비동기처리가 필요한 환경에서 호출한다.

보이는 대로 다 적어봤지만, 사실 머리로 이해가 안되는건 여전하다. 결국 실제로 사용해보면서 배워나가야 제대로 이해가 될 것이다...

profile
생각 없는 개발자

0개의 댓글