리액트 쿼리를 사용하는 이유는 무엇일까?
여러가지 장점이 있지만 서버의 상태와 클라이언트의 상태를 명확하게 분리할 수 있다는 것만으로도 리액트 쿼리를 사용하는 것이 충분히 의미있다는 결론을 내렸다.

서버 상태와 클라이언트의 상태를 분리함으로써 얻을 수 있는 이점
- 특성이 다른 서버 상태와 클라이언트 상태를 분리하여 관리함으로써 상태 관리 효율성 향상 
- 코드 간결, 유지보수성 향상
- 신뢰할 수 있는 서버 데이터 (최신 데이터)

 

2018년 미국에서 GraphQL과 Apollo Client가 인기를 끌었을 때, "Redux는 이제 끝인가요?"라는 질문이 많았다고 한다. 

일부 데이터를 가져오는 라이브러리가 전역 상태 관리 라이브러리를 대체한다는 게 무슨 소리일까?

 

Apollo는 원하는 데이터를 정의하고 가져오는 것 뿐만 아니라 해당 서버 데이터에 대한 캐시도 함께 제공한다.

즉, 여러 구성 요소에서 동일한 useQuery 훅을 사용할 수 있으며, 데이터를 한 번만 가져온 다음 캐시에서 데이터를 반환한다. 

서버에서 데이터를 가져와 어디에서나 사용할 수 있다는 것은 Redux를 사용하는 이유와 비슷하게 들린다.

 

2019년 말 React Query는 이러한 Apollo의 장점을 가져와 만들어졌다. 

 

상태란?

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

→ 개발자가 관리해야 하는 데이터들

 

상태 관리

모던 웹 프론트엔드 개발에서 UI/UX의 중요성과 함께 프로덕트 규모가 커지고 FE에서 수행하는 역할이 늘어났다.

이는 프론트엔드에서 관리하는 상태가 많아졌다는 것을 의미한다. 

프론트엔드에서의 상태 관리 필요성 증가

Client State vs Server State

[클라이언트 상태]

  • 클라이언트에서 소유하며 온전한 제어 가능
  • 초깃값 설정이나 조작에 제약이 없음
  • 다른 사람들과 공유되지 않으며 사용자와의 상호작용에 따라 변할 수 있음
  • 항상 클라이언트 내에서 최신 상태로 관리됨

 

[서버 상태]

  • 클라이언트에서 제어하거나 소유되지 않은 원격의 공간에서 관리되고 유지
  • Fetching이나 Updating에 비동기 API 필요
  • 다른 사람들과 공유되는 것으로 사용자가 모르는 사이에 변경될 수 있음
  • 신경 쓰지 않는다면 잠재적으로 옛날 데이터가 될 가능성을 지님

→ 사실상 프론트에서 해당 값들이 저장되어 있는 state는 일종의 캐시이다.

 

React Query

React Query makes fetching, caching, synchronizing and updating server state
in your React applications a breeze.

 

Fetching

useQuery를 이용하여 데이터를 조회한다. 

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.

 

Updating

useMutation을 이용하여 데이터를 생성, 수정, 삭제한다. 

Unlike queries, mutations are typically used to create/update/delete data or perform server side-effects. 

 

Caching and Synchronizing

리액트 쿼리의 컨셉은 RFC 5861에 있는 stale-while-revalidate의 아이디어를 차용했다. 

stale-while-revalidate: 백그라운드에서 stale response를 revalidate하는 동안 캐시가 가진 stale response를 반환한다.

*stale: 신선하지 않은 (stale 데이터는 최신화가 필요한 낡은 데이터를 의미)

→ Latency가 숨겨지므로 사용자에게 로딩 스피너와 같은 로더를 보여주지 않아도 된다.

 

[cacheTime / staleTime]

위 컨셉을 리액트 쿼리에 적용하기 위해서는 다음과 같은 옵션을 사용한다. 

  • cacheTime: inactive 상태로 메모리에 남아있는 시간을 의미한다. 기본값은 5분이다. inactive 상태로 지정한 cacheTime이 지나면 가비지 콜렉터에 의해 제거된다.
  • staleTime: 얼마의 시간이 흐른 후에 데이터를 stale 취급할 것인지를 의미한다. 기본값은 0이다. 

 

[refetch 조건]

stale한 상태가 되면 다음과 같은 상태일 때 refetch가 발생한다. 

  1. 쿼리가 마운트 될 때 
  2. 브라우저 화면을 이탈했다가 다시 포커스할 때
  3. 네트워크가 다시 연결될 때

위 상황에서 refetch가 발생하는 이유는 관련된 옵션들의 기본값이 모두 true이기 때문이다. 

refetchOnMount / refetchOnWindowFocus / refetchOnReconnect: 해당 시점에 데이터가 stale한 상태이면 refetch

 

리액트 쿼리 상태 흐름

[출처] React Query와 상태관리 :: 2월 우아한테크세미나

 

리액트 쿼리 장점

  • 서버 상태 관리가 용이하며 직관적인 API 호출 코드
  • API 처리에 관한 각종 인터페이스(e.g. isLoading..) 및 옵션(e.g. onSuccess..) 제공
    • API 로딩, 에러 여부와 같은 상태를 관리하기 위한 규격화된 방식 제공
    •  API 상태 관리 보일러 플레이트 감소
  • 서버 상태와 클라이언트 상태의 분리
  • 캐싱 전략이 필요할 때 유용

 


참고 레퍼런스

 

복사했습니다!