새소식

FE/React

[React]React-Query 이해하기

  • -

1. React-Query 

 -  리액트 쿼리는, 서버에서 가져온 데이터를 웹 브라우저 앱에서 사용하기 쉽게 도와주는 기술

 - 서버는 클라이언트에게 데이터베이스에 있는 정보를 전달해주는 역할을 한다

   > 이 때, 서버:api서버 / 클라이언트: 리액트 앱(웹 브라우저에서 실행되는, 우리가 작성한 앱)

 

server state / client state를 가지고 있는 어플리케이션의 아키텍쳐 구조

 

  • 데이터베이스에서 가져온 데이터를 클라이언트에서 보여주기 위해 우리는 ajax를 이용하는데, 이 때 서버에서 가져오는 데이터를 '서버의 상태'라고 이야기 한다. (서버 스테이트)
  •       서버는, 데이터 베이스에서 기록된 정보 (ex.유저 기록)를 불러온다. 이러한 정보들을 조합해서, 서버state를 만들고, 클라이언트에게 그것을 응답으로 내려준다(  ajax호출을 통해)
  •      클라이언트는, 서버에서 받은 해당 정보를 가져다가, 클라이언트에서 사용하기에 간편한 형태로 재조합하여, 클라이언트 state를 만든다.
Client state
  • client state는 크게 두 가지로 나눌 수 있다.
1. client에서 자체적으로 만드는 state(최초 데이터의 발생지가 클라이언트)

2. server에서 전달받은 값으로 만드는 state(최초 데이터 발생지가 서버)

 < client가 자체적으로 만드는 state>

  -대개, UI를 담당하는 부분

    ex) 모달이 열리고 닫혔는지, 어떤 버튼이 클릭되었는지, 지금 창이 리사이징 되고 있는지, 현재 웹사이트가 다크모드인지 라이트모드인지에 대한 메타 정보를 담은 상태값

 < 서버state -> client state로 가져오는 부분>

 - 서버의 상태값을 받아오는데에, 리액트에서는 정해진 모범답안은 없음

- 컴포넌트의 생명 주기를 파악한 후 적절한 시점에 ajax호출을 하고 서버에서 데이터를 받아온다. -> 이를 internal state나 external state도구를 통해, 서버state를 컴포넌트 state로 wrapping한 이후, 서버 state를 클라이언트 state로 사용한다.

-useState를 사용할 경우, 데이터를 불러와 setState호출을 통해, 응답 당시의 server state를 component state로 wrapping한다.

useEffect(() => {
 customFetch("...").then(setState)
},[]);

=> 이렇게 클라이언트 앱은 server state와 client state에 대한 로직 처리를 나누어 선언해주어야 함

 

 

  • 리액트 개발자가 사용하는 상태관리는 크게, external state와, internal state로 나뉜다.  
 1. external state: 리덕스,몹엑스,저스탠드,조타이,리코일 등등
 
 2. internal state : context api, useState

         

 

2. react query

React-Query 장점

1. 간편한 server state 수급 방식

  1. 서버 데이터 캐싱
  2. 데이터 패칭 시 로딩, 에러 처리를 한 곳에서 처리 가능
  3. prefetching, retry 등 다양한 옵션
  4. 쉬운 상태 관리

 

React Query의 라이프 사이클
  • fetching - 데이터 요청 상태
  • fresh - 데이터가 프레시한(만료되지 않은) 상태.
    • 컴포넌트의 상태가 변경되더라도 데이터를 다시 요청하지 않는다.
    • 새로고침 하면 다시 fetching 한다.
  • stale - 데이터가 만료된 상태.
    • 데이터가 만료되었다는 것은 서버에서 한번 프론트로 데이터를 주면 그 사이에 다른 유저가 데이터를 추가, 수정, 삭제 등등 할 수 있기 때문에 만료되었다고 한다. (최신화가 필요한 데이터)
    • 컴포넌트가 마운트, 업데이트되면 데이터를 다시 요청합니다.
    • fresh에서 stale로 넘어가는 시간 -> 기본값 0
  • inactive - 사용하지 않는 상태.
    • 일정 시간이 지나면 가비지 콜렉터가 캐시에서 제거함
    • 기본값 5분
  • delete - 가비지 콜렉터에 의해 캐시에서 제거된 상태.
fetching -> fresh -> stale -> inactive -> delete

https://velog.io/@yrnana/React-Query%EC%97%90%EC%84%9C-staleTime%EA%B3%BC-cacheTime%EC%9D%98-%EC%B0%A8%EC%9D%B4

3. 사용 방법

 1. React-Query 준비

상위에서 QueryClient를 생성 후 넣어준다.

ReactQueryDevtools는 React-Query의 개발도구이다.

2. 데이터 패칭 

useQuery를 이용해서 데이터를 불러올 수 있습니다.

특징으로는 React Hook을 활용한다는 점과 queryKey가 캐싱의 핵심이며 상태 관리도 이 부분을 이용해서 할 수 있을 것 같습니다.

 

 

API를 기다리는 동안은 loading 상태인데, 성공할 경우 값이 들어오는 것을 볼 수 있습니다.

3. 데이터 업데이트

useMutation을 사용해서 데이터를 업데이트합니다.


여기서도 중요한 것이 있습니다. 그냥 useMutation을 통해서 데이터만 업데이트하게 되면, 서버에만 데이터 수정사항을 보내는 것입니다.

프론트에서는 데이터가 fresh하지 않기 때문에 test5가 추가된 것을 모릅니다.

이럴 경우 사용자 경험이 좋지 않습니다!

 

보통 이럴 경우에는 2가지 방법이 있는데

1. get을 한번 더 해서 리스트를 초기화한다.

2. useState를 활용, 기존 Array에 push 해서 setState를 해준다.

 

1안 같은 경우에는 서버의 리소스를 사용하는 거라 지양하고 2안을 지향합니다.

하지만 2안을 하려면 매우 귀찮은 짓을 해야 하는데, React Query에서는 그나마 편하게 바꿔줄 수 있습니다.

 

useMutation Hook의 onMutate에서 setQueryData를 이용해 해당 키의 데이터를 수정해주는 방식입니다.

이렇게 하면 사용자 경험이 매우 좋아질 수 있고, 필요 없는 네트워크 비용을 줄일 수 있습니다.(엄청 중요한 리스트면 다시 불러야겠죠?)

그럴 경우 네트워크를 타지 않고 프론트에서 추가된 값을 보여줄 수 있습니다.

 

기본적인 데이터 패칭, 업데이트만 조사해봐도 React-Query의 장점이 많이 보이는 것 같습니다.

 

 

 

Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.