Flutter의 서버 상태
서버 데이터에는 상태 클래스를 하나 더 두기보다 캐시가 필요해요. 캐시는 모든 화면에 같은 데이터를 주고, 로딩과 에러를 추적하고, 오래된 데이터를 다시 가져와요.
Flutter 앱이 보여주는 데이터는 대부분 할 일 목록, 프로필, 검색 결과 페이지처럼 서버에서 와요. 이 데이터는 앱이 소유한 상태와 다르게 동작해요.
- 앱이 소유하지 않아요. 데이터는 앱에 알리지 않고 서버에서 바뀌어요.
- 여러 곳에서 공유해요. 여러 화면이 같은 목록을 보여주고, 화면끼리 내용이 같아야 해요.
- 늦게 도착하거나 아예 도착하지 않아요. 읽을 때마다 로딩 상태와 에러 상태가 있어요.
- 시간이 지나면 오래된 데이터가 돼요. 1분 전에 가져온 목록이 지금은 틀릴 수 있어요.
어느 탭을 선택했는지 같은 앱 상태에는 이런 문제가 하나도 없어요.
| 앱 상태 | 서버 데이터 | |
|---|---|---|
| 바꾸는 쪽 | 직접 작성한 코드 | 서버, 언제든지 |
| 원본이 있는 곳 | 앱 | 다른 곳 |
| 도착하는 시점 | 바로 | 나중에, 또는 도착하지 않음 |
| 오래된 데이터가 되는지 | 아니요 | 예 |
서버 데이터를 앱 상태와 같은 곳에 두면 캐시를 직접 만들어야 해요. 리포지토리 안의 캐시, 화면마다 두는 로딩 플래그, 새로고침 메서드, 서버에 쓸 때마다 무효화하는 코드, 두 화면이 동시에 요청할 때의 규칙이 모두 필요해요.
캐시가 해주는 일
섹션 제목: “캐시가 해주는 일”Fuery는 서버 데이터를 캐시 하나에 키로 나눠 둬요.
final todosQuery = Query( queryKey: ['todos'], queryFn: (_) => api.getTodos(),);이 정의 하나로 캐시가 이렇게 동작해요.
- 키 하나에 사본 하나.
['todos']를 사용하는 화면은 모두 같은 캐시 항목을 읽어요. - 요청은 한 번에 하나. 데이터를 가져오는 동안 요청한 화면은 그 요청을 공유해요.
- fresh 상태였다가 stale 상태로. 데이터는
staleTime동안 fresh 상태예요. 기본값은 0이라서 데이터는 도착하자마자 stale 상태가 돼요. - 이전 데이터는 화면에 남아요. Fuery가 백그라운드에서 다시 가져오는 동안 화면은 이전 데이터를 계속 보여줘요.
- 알아서 다시 가져와요. 화면이 stale 데이터를 사용하기 시작하거나 앱이 포그라운드로 돌아오면 Fuery가 그 데이터를 다시 가져와요. 연결 상태 소스가 있으면 네트워크가 다시 연결될 때도 다시 가져와요(네트워크가 다시 연결될 때).
- 쓰고 나면 다시 가져와요. 뮤테이션 뒤에
['todos']를 무효화하면 Fuery가 화면의 목록을 다시 가져와요. - 로딩과 에러가 데이터와 같이 와요. 결과에는
status,error, 그리고isRefetching같은 플래그가 있어요. 그래서 화면은 이 값을 직접 추적하지 않고 읽기만 해요. - 사용하지 않는 데이터는 메모리에서 사라져요. 어떤 화면도 사용하지 않는 데이터는
gcTime(가비지 컬렉션 시간, 기본값: 5분)이 지나면 Fuery가 제거해요. 기기에 저장한 데이터는 기기에 그대로 남아요.
캐시된 데이터가 거치는 단계와 단계마다 끝나는 조건은 쿼리 생명주기에 있어요.
캐시가 동작하는 곳
섹션 제목: “캐시가 동작하는 곳”캐시는 위젯 트리의 일부가 아니라 평범한 Dart 객체예요. 같은 쿼리가 세 곳에서 동작해요.
QueryBuilder가 쿼리를 렌더링해요.- Cubit이
todosQuery.observe()의stream을 구독해요. - 스크립트가
client.query(todosQuery)를await로 기다려요.
Fuery는 지금 사용하는 상태 관리를 대체하지 않아요. Cubit과 Bloc 안에서 쿼리를 사용하는 방법은 Bloc과 Cubit에 있어요.
다음 단계
섹션 제목: “다음 단계”- 캐시가 동작하는 방식: 정의, 클라이언트, 옵저버, 캐시된 데이터의 생명주기
- 시작하기: Fuery를 설치하고 첫 요청을 캐시하기
- 쿼리: 키, fresh 상태, 옵션
- 데모 사용해보기: 브라우저에서 실행하는 예제 앱과 개발자 도구