Flutter

상태 관리란 뭘까? - riverpod 2.x

whs5758 2025. 8. 22. 18:48

상태 이해하기

상태(State)란 변수에 담긴 값입니다. 또는 시간이 지남에 따라 변경될 수 없거나 변경될 수 있는 변수에 담긴 값이라고 볼 수 있습니다.

상태: 앱이 실행되는 동안 변경될 수 있는 정보

예시: 사용자 입력값, 로그인 여부, 카운터 숫자, 로딩 상태 등

 

StatelessWidget - StatelessWidget은 상태를 변경할 수 없습니다.

StatefulWidget - StatefulWidget은 상태를 변경할 수 있습니다.

 

상태(State)의 종류

상태는 공유 여부에 따라 로컬 상태(Local State) 공유 상태(Shared State)로 나눌 수 있습니다.

  • 로컬 상태(Local State) : 공유되지 않는 상태
    • BottomNavigationBar의 현재 선택한 탭
  • 공유 상태(Shared State) : 여러 위젯에서 공유되어 표현되는 상태
    • 로그인한 유저 정보
    • 특정 게시글의 좋아요 표시
    • 쇼핑 앱의 장바구니

공유 상태 상태가 변경될 경우, 동일한 상태를 보여주기 위해 동기화가 필요합니다.

공유 상태가 변경될 때, 동기화 하는 것상태 관리(State Management)라고 합니다.

상태 관리가 안되면 데이터 일관성을 잃게 됩니다.

  • 유저가 프로필을 변경해도 다른 화면에서 이전 프로필이 보이는 문제
  • 쇼핑 바구니에 표시된 상품의 개수와 실제 담긴 상품 개수가 다른 문제
  • 글을 작성했는데, 게시판에 반영되지 않는 문제(Create)
  • 글을 수정했는데, 게시판에 반영되지 않는 문제(Update)
  • 글을 삭제했는데, 게시판에 반영되지 않는 문제(Delete) 

동일한 데이터를 여러 곳에서 가지고 있기 때문에, 동기화가 필요하게 됩니다.

 

데이터를 한 곳에서 관리하면 동기화 문제가 해결됩니다. 따라서 모든 상태 관리 방법들은 공유 상태를 한 곳에서 관리하도록 중앙 집중식으로 만들어 문제를 해결합니다.


Riverpod의 세계: 데이터 창고 이야기

옛날 옛적, Flutter 왕국에는 수많은 건물(위젯)들이 있었습니다. 건물들은 각자의 일을 처리하며 잘 돌아갔지만, 한 가지 문제가 있었죠. 건물들끼리 자주 사용하는 물건(데이터)을 공유하기가 너무 어려웠던 겁니다.

어떤 건물은 "장바구니"에 담긴 물건이, 또 다른 건물은 "사용자 정보"가 필요했습니다. 그래서 서로 직접 물건을 주고받았지만, 물건을 받기 위해 여러 건물을 거쳐야 하는 비효율(Prop Drilling)이 발생했고, 결국 왕국은 혼란에 빠졌습니다.

이때, 똑똑한 현자가 나타나 해결책을 제시했습니다. 바로 "Riverpod 창고 시스템"을 도입하는 것이었죠. 이 창고 시스템은 Flutter 왕국 전체의 데이터와 물건을 안전하고 효율적으로 관리하는 혁신적인 방법이었습니다.


창고 시스템의 핵심: 설계도와 실제 창고

Riverpod 창고 시스템은 세 가지 핵심 요소로 구성됩니다:

  • 창고 데이터(State): 실제로 보관되는 물건들 (사용자 정보, 장바구니 내용 등)
  • 창고 운영 매뉴얼(Notifier): 창고를 어떻게 관리할지 정해놓은 설계도와 규칙들

현자는 이렇게 설명했습니다: "창고를 짓기 전에 먼저 설계도부터 그려야 한다. 그 설계도에는 창고를 어떻게 운영할지, 물건을 어떻게 넣고 빼고 정리할지에 대한 모든 방법이 담겨 있어야 한다."

  • 실제 창고를 개설 (Providers)

다양한 종류의 창고들

Provider (기본 창고)

가장 기본이 되는 창고입니다. 이 창고에는 "한번 정해지면 바뀌지 않는 물건"들이 보관되어 있습니다. 예를 들어, "상품 목록"이나 "앱 설정값" 같은 것들이죠. 이 창고는 물건이 변하지 않기 때문에 복잡한 운영 매뉴얼이 필요 없습니다. 그냥 문을 열어두고 누구든지 와서 물건을 확인할 수 있게 해두면 됩니다.

NotifierProvider (관리형 창고)

이 창고에는 상세한 운영 매뉴얼이 있습니다. 매뉴얼에는 "장바구니에 물건을 추가하는 방법", "사용자 로그인 처리하는 방법" 등의 전문 절차들이 기록되어 있습니다.

건물들(위젯들)이 이 창고에 와서 "장바구니에 사과를 추가해주세요!"라고 요청하면, 창고는 미리 정해진 절차에 따라 안전하게 작업을 처리합니다. 매뉴얼에 없는 방법으로는 절대 물건을 변경할 수 없기 때문에, 모두가 안심할 수 있었습니다.

AsyncNotifierProvider (원격 창고)

이 창고는 특별히 "멀리 있는 창고에서 물건을 가져오는 일"을 담당합니다. 즉, 인터넷 통신을 통해 데이터를 가져오는 거죠.

이 창고의 매뉴얼은 매우 똑똑해서, 물건을 가져오는 동안에는 창고 입구에 "배송 중..." 표시를 해두고, 물건이 도착하면 실제 데이터로 교체합니다. 만약 배송 중에 문제가 생기면 "배송 실패" 표시를 창고에 걸어두어 모든 건물들이 상황을 알 수 있게 했습니다.


창고와 건물들의 소통 방법

이제 건물들은 직접 물건을 주고받는 대신, 창고들을 통해 데이터를 공유하기 시작했습니다. 현자가 정한 소통 방식은 세 가지였습니다.

1. 창고 상태 실시간 확인 (ref.watch) - 계속 보다

건물이 창고에 가서 "창고 상태를 계속 지켜보겠습니다!"라고 선언하는 것입니다. 이렇게 선언한 건물은 창고의 "단골 고객"이 됩니다.

창고의 내용물이 바뀌면, 단골 고객인 건물들에게 즉시 "내용이 바뀌었어요!"라고 알려줍니다. 그러면 건물들은 새로운 상태에 맞춰 자기 모습을 업데이트합니다. 마치 상점의 진열창이 바뀌면 지나가던 사람들이 "어? 뭔가 달라졌네?"하고 눈여겨보는 것과 같습니다.

2. 창고 작업 요청 (ref.read) - 한번만 요청할 때

건물이 창고에 가서 "이 작업 좀 해주세요!"라고 요청하는 것입니다. 예를 들어 "장바구니에 이 물건 추가해주세요!" 또는 "사용자 로그인 처리해주세요!"라고 말이죠.

이 경우에는 작업만 요청하고 창고 상태를 지켜보지는 않습니다. 마치 택배를 부치러 우체국에 갔다가 그냥 돌아오는 것과 같습니다. 주로 버튼을 눌렀을 때처럼, 한 번의 행동을 위해 사용합니다.

3. 창고 변화 알림 받기 (ref.listen) - 알림 받기

건물이 창고에게 "특별한 일이 생기면 저에게 알려주세요!"라고 부탁하는 것입니다. 창고 상태를 직접 보지는 않지만, 특정 변화가 발생하면 알림을 받아서 특별한 행동을 할 수 있습니다.

예를 들어, 장바구니에 물건이 추가되면 "상품이 추가되었습니다!"라는 메시지를 띄우거나, 로그인이 완료되면 메인 화면으로 자동 이동하는 것 같은 일들이죠. 마치 화재 경보기처럼, 평소에는 조용히 있다가 특별한 상황이 발생했을 때만 반응합니다.


창고 시스템의 장점

이렇게 창고 데이터와 창고 관리자 시스템이 도입된 후, Flutter 왕국은 훨씬 효율적이고 안전해졌습니다:

  • 중앙 집중 관리: 모든 중요한 데이터가 창고에 체계적으로 보관됨
  • 안전한 변경: 오직 전문 창고 관리자만이 데이터를 변경할 수 있음
  • 실시간 동기화: 데이터가 바뀌면 관련된 모든 건물이 자동으로 업데이트됨
  • 효율적 소통: 건물들이 서로 직접 연락할 필요 없이 창고를 통해 소통