자바스크립트 - React.js

[ReactQuery] Query Key - 의존성 배열을 활용해보자 !

Lv1_junior_dev 2023. 7. 14. 20:11

 

❗ Query Key

기본적으로 리액트 쿼리는 쿼리의 고유한 key를 바탕으로 해당 쿼리에 대한 캐싱을 관리한다.
쿼리 키는 단순히 문자열을 포함하는 배열에서부터, 중첩 객체를 가지는 배열이 될 수도 있다.
쿼리 키가 고유하고, 직렬화를 가능한 한 사용할 수 있다.

✔ 단순한 Query key
주로 리스트나, 인덱스 리소스, 위계가 없는 리소스에 대해서는 쿼리 키를 작성한다.

 const { data: appointments = fallback } = useQuery(
    [queryKeys.appointments],
    () => getAppointments(monthYear.year, monthYear.month)
  );

하지만 단순한 쿼리키의 문제점이 있다.

바로 문제점에 대해 쉽게 이해할 수 있도록 예시를 통해 살펴보자

이러한 달력이 있고 예약 사항을 React Query를 통해 관리한다고 가정해보자.

예약 정보는 appointments라는 쿼리키를 통해 데이터를 가져오고 있다.

여기서 발생하는 문제는 뭘까 ? 

문제는 바로 동일한 Query key를 가지고있다보니 

다음 월로 이동했을때도 이전에 있던 데이터가 동일하게 다음 월으로 불러와버린다.

왜 이러한 문제가 발생하냐면 모든 쿼리에 동일한 Query key를 사용해버리기 때문이다.

그렇기 때문에 이전 달이나 다음 달 버튼을 클릭 했을 때 쿼리 데이터는 만료(stale) 상태지만 리페치(refetch)를 트리거 할 대상이 없다. 그렇기 때문에 이러한 상황 같은 경우 매 월에 고유한 Query key를 갖게하면 해결이 된다.

 

Query key는 항상 의존성 배열로 취급하게하여 데이터가 변경될 경우 키도 변경되어 각 데이터에는 고유한 쿼리키를 갖도록 해야한다. 

 

이해했다면 발생한 문제를 해결해보자. 

 

✔ 고유한 값을 갖는 Query key

  const { data: appointments = fallback } = useQuery(
    [queryKeys.appointments, monthYear.year, monthYear.month],
    () => getAppointments(monthYear.year, monthYear.month)
  );

일단 앞서 설명한 부분에 따르면 Query key는 이러한 형태로 만들어지는게 옳은 형태라고 볼 수 있다.

추가적으로 알아두면 좋을 부분이 배열의 첫 번째 항목에는 데이터 무효화를 하기위해 모든 배열의 공통점이 되는 공통 접두사로 해두는게 좋다. 그러면 나중에 한 번에 무효화를 할 수 있기 때문이다.

 

** 해당 useQuery에서는 queryKeys의 상수를 다른 파일에서 가져왔는데 queryKeys.appointments에는 "appointments"라는 문자열이 들어있다. 이렇게 문자열을 상수로 관리하는 이유는 오타같은 사소한 문제로 인해 발생하는 상황을 예방하기 위해서다. 

 

이렇게 각 데이터별 고유한 Query Key를 지정했다면

해당 사진처럼 올바르게 동작하는걸 보게될 수 있을것이다.

아래 ReactQueryDevtools를 보면 각 Query key가 배열의 공통점이 되는 공통 접두사로 이루어져 있고 두 번째와 세 번째 항목은 각 Query key의 고유한 항목이 되는 년도와 월으로 이루어져 있는것을 확인할 수 있을 것이다.

 

파이팅 ㅎ