숨참고 개발다이브

[React / React Native] 우아한 테크세미나 - React Query 와 상태관리 정리 본문

개발/React & React Native

[React / React Native] 우아한 테크세미나 - React Query 와 상태관리 정리

사라 Sarah 2024. 2. 19. 18:46
728x90

 

현재 업무 프로젝트에서는 Redux를 사용 중인데, 서비스의 기능과 규모가 커질수록 redux, saga로 인해 코드가 복잡해지는 느낌이 있었다. 이를 개선하기 위한 방법을 고민하게 되었고, 국내 빅테크 기업에서도 React Query로의 전환 사례가 적지 않게 보여 react-query 적용을 결정하게 되었다.

 

적용 전, react query에 대해 다시 정리하고 공부하는 시간을 가지게 되었다.

 

 

 


 

우아한 테크세미나 영상

https://www.youtube.com/watch?v=MArE6Hy371c

 

 

 


 

상태관리

상태란?

주어진 시간에 대해 시스템을 나타내는 것으로 언제든지 변경될 수 있음

즉 문자열, 배열, 객체 등의 형태로 응용 프로그램에 저장된 데이터

관리해야하는 데이터들

 

상태관리란?

상태를 관리하는 방법에 대한 것 > 프로덕트가 커짐에 따라 어려움도 커짐

상태들은 시간에 따라 변화함

React에서는 단방향 바인딩이므로 Props Drilling 이슈 존재

Redux, MobX 같은 라이브러리 활용해 해결

 

 

배민 주문FE팀의 고민..

배민 FE의 Redux Store 래거시..

  • API 통신 관련 코드가 Store에 있음
  • 반복되는 isFetching, isError 등 상태
  • 반복되는 비슷한 구조의 API 통신 코드

 

서버에서 받아야하는 상태들의 특성

 

두 가지의 상태

 

 

 


 

React Query

Overview

fetching, caching, synchronizing and updating server state in React App

=> 서버 데이터를 가져오고, 캐싱하고, 동기화하고 업데이트하는 라이브러리

zero-config로 즉시 사용가능하나 커스텀도 가능

 

Queries

A query is a declarative dependency on an asynchronous source of data that is tied to a unique key. A query can be used with any Promise based method (including GET and POST methods) to fetch data from a server. If your method modifies data on the server, we recommend using Mutations instead.

데이터 Fetching용 ⇒ CRUD 중 Reading에만 사용

 

Query Key

Key, Value 매핑구조와 비슷한 맥락

React Key에 따라 query caching을 관리함

v4부터는 Array 타입만 가능

 

Query Function

Promise를 반환하는 함수 > data resolve or error throw

 

useQuery

useQuery(QueryKey, QueryFucntion)

  • data: response
  • error
  • isFetching: Request가 in-flight(진행 중)일 때 boolean값
  • status, isLoading, isSuccess, isLoading 등: query 상태
  • refetch: query refetch하는 함수 제공
  • remove: query cache에서 지우는 함수 제공

 

useQuery Option(custom config)

options를 통해 커스텀이 가능하다.

기타 Option은 docs 참고

 

queries 파일 분리

 

배민에서는 도메인 별로 묶어서 관리 중!

 

 

Q&A (1)

  • 2번을 사용하면 코드 복잡도가 올라감 가능하면 1번을 사용

 

  • Option의 onSuccess에서 액션을 dispatch

 

728x90

 

Mutations

Unlike queries, mutations are typically used to create/update/delete data or perform server side-effects. For this purpose, React Query exports a useMutation hook.

=> 데이터 생성/수정/삭제 용!

Promise 반환 함수만 있어도 사용 가능

 

useMutation

 

useMutation Option

  • onMutate: 본격적인 Mutation 동작 전 먼저 동작하는 함수, Optimistic update 적용 시 유용

* Optimistic update란?

  • API 요청을 낙관적(Optimistic)으로 성공할 것으로 보고 UI를 먼저 업데이트, 실패 시 UI 롤백

 

Query Invalidation

queryClient를 통해 Invalidate 메소드를 호출하면 됨

해당 key를 가진 query는 stale (신선하지 않은, 낡은 데이터) 취급되고, 현재 rendering 되고 있는 query들은 백그라운드에서 refetch

 

 


 

React Query의 Caching & Synchronization

React Query의 컨셉

 

  • stale response
    • 클라이언트에서 받은 데이터가 최신이 아님
  • Cache-Control: max-age=600, stale-while-revalidate=30
    • 600초 동안 캐시데이터를 유효하다고 보고 600초가 지난 시점부터 해당 데이터는 stale 취급
    • stale-while-revalidate는 max-age 가 지나고 해당 시간 동안 refetch 하면서 보여주겠다.

 

컨셉을 메모리 캐시에도 적용

  • cacheTime
    • 메모리에 얼마만큼 있을 건지(default 5분)
  • staleTime
    • 얼마의 시간이 흐른 후 데이터를 stale 취급할지(default 0분)
  • refetchOnMount / refetchOnWindowFocus / refetchOnReconnect
    • true면 Mount, window focus, reconnect 시점에 data가 stale이라고 판단되면 모두 refetch (default true)

 

Query 상태흐름

  1. fetching이 먼저 일어남
  2. staleTime이 만료되기 전까지 fresh 상태 유지
  3. staleTime이 만료되면 stale 상태가 됨
  4. 스크린에서 날아가면(cacheTime이 만료되면) active에서 inactive 상태로 변경됨
  5. 가비지 콜렉터가 처리되며 deleted

 

* 조금 더 복잡한 쿼리

 

 

zero-config 역할

 

 


 

React Query의 값 관리

QueryClient 내부적으로 Context 사용

 

전역상태처럼 관리되는 데이터들.. → Context API 사용됨

 

 


 

React Query 사용 후 배민 주문팀 FE 프로덕트

React Query 사용 시 장점

Redux, MobX 등을 사용할 때보다 서버 상태 관리가 용이, 직관적인 API 호출 코드

API 처리에 관한 각종 인터페이스 및 옵션 제공

Client Store가 FE에 정말 필요한 전역상태만 남아 Store 답게 사용됨(Boilerplate가 감소됨)

devtool 제공으로 원활한 디버깅 가능

Cache 전략이 필요할 때 좋음

 

고민이 필요한 부분

컴포넌트가 상대적으로 비대해지는 문제

좀 더 난이도 높아진 프로젝트 설계

React Query의 장점을 더 잘 활용할 방법 => 단순히 API 통신만을 위해 사용하지 않도록..

 

React Query 추천

많은 전역상태가 API 통신과 엮여있어 비대해진 Store가 고민될 때

API 통신 관련 코드를 간단하게 구현하고 싶을 때

FE에서 데이터 캐싱 전략에 고민이 많을 때

 

 

 


 

Q&A (2)

Q1) query key 중복 관리?

  • 쿼리를 도메인별로 모으다 보니 중복되지 않음, 여러 곳에서 사용하면 enum값으로 사용하자고 제안하기도 했음
  • 함수명, 변수명을 쿼리키로 사용하기도 함

 

Q2) 화면에서도 공통적으로 사용하는 쿼리들을 도메인을 어떻게 분리하는지?

  • 배너, 오더 등의 단위로 도메인을 분류하는 단위가 있음
  • core라는 도메인에 사용할 것 같음

 

Q3) 배민 주문팀의 default option?

  • API별로 커스텀하고 특성이 달라 개별 옵션으로 관리함

 

Q4) Redux와 React-Query 같이 사용할 때 구조 설계 방법?

  • 클라이언트, 서버 별개로 생각하는 게 좋음

 

 

300x250
Comments