React Query 공부 (2) - useQuery

JunSeok·2023년 1월 15일
0

react-query

목록 보기
3/11
post-thumbnail

이전 post에서 간단한 useQuery 사용법을 다루었다.
다시 간단하게 코드를 적어보겠다.

const { data } = useQuery("posts", fetchPosts);

query key에 해당하는 cache data는 refetch 되는 상황이 아니면 같은 값을 유지한다.
그리고 cache data는 앞서 말했듯이 stale한 상태에서만 refetch되는데
query key에 해당하는 query의 data는 다음과 같은 상황들에서만 refetch된다.

  • component remount
  • window refocus
  • running refetch function
  • automated refetch
  • query invalidation after a mutation

query key는 같지만 query function에 들어가는 인자 값이 다른 상황

위 서술한 내용을 인지하고 다음과 같은 상황을 해결해보자

const fetchComments = async () => {
 	const response = await fetch(
    `https://jsonplaceholder.typicode.com/comments?postId=${postId}`
  );
  return response.json(); 
}

같은 query key을 가지고 있고 query function에 서로 다른 인자가 필요한 상황이다.
그렇다면 다른 post id가 들어갈 때마다 그에 맞는 다른 데이터를 반환해야 할 것이다. 하지만 앞서 말했듯이 refetch 되는 상황이 아니면 data는 이전에 fetching한 같은 값을 유지한다. query key가 동일하기 때문이다.

이전방법과 같은 방법으로 data를 불러와보자
(아 그리고 인자가 필요한 함수인 경우 익명함수를 통해 함수를 실행시켜야 한다.)

const { data } = useQuery("comments", () => fetchComments(post.id));

위와 같은 이전과 같은 방법으로 데이터를 fetching 하면 다른 post.id를 넣어도 query key는 같기 때문에 이전에 만들어진 cache data만 불러오게 된다.

이를 어떻게 해결해야 할까?

solution

단순하게 생각해보면 다른 인자를 가져올 때마다 기존의 query key가 가지고 있는 cache data를 삭제하는 것이다.
하지만 굳이 그렇게 하지 않아도 될 뿐만 아니라 비효율적인 방법이다.
만들어진 cache data는 나중에 다시 사용하면 되기 때문이다.

query는 post.id라는 인자를 포함하고 있다. 그리고 하나의 동일한 query key마다 하나의 캐시를 가질 수 있으며 캐시를 공유하지 않는다. 즉 하나의 query key와 서로 다른 post.id마다 서로 다른 하나의 cache data가 주어지는 것이다.
그래서 각 post.id마다 다른 query에 레이블을 형성할 수 있다.

간단한 예를 들어보자면 다음과 같다.

query keypost.idcache data
"comments"11번에 해당하는 data
"comments"22번에 해당하는 data
"comments"33번에 해당하는 data
"comments"44번에 해당하는 data

같은 query key에 서로 다른 post id마다 다른 cache data를 가진다.

만약 제일 최신 데이터가 4번이라면 4번 데이터는 stale 상태가 되고 나머지 1, 2, 3번은 inactive 상태가 되어 cache time(default time은 5분, 즉 300000ms)이 지나면 쓰레기 데이터가 될 것이다.

실제 코드를 통한 해결

우리는 query key를 문자열 대신 query key와 인자가 포함된 배열을 전달함으로써 이 문제를 해결할 것이다.
배열의 첫번째 element로 query key가 들어가고 두번째 element로 인자가 들어간다.
이 배열은 우리가 흔히 알고 있는 useEffect에서 사용하는 dependency array와 같은 역할을 할 것이다.

간단한 사용예시를 보자

const { data } = useQuery(["comments", post.id], () => fetchComments(post.id))

다음과 같이 코드를 짜면 dependency array처럼 post.id가 바뀔 때마다 react-query는 내부적으로 위의 표처럼 새로운 query를 만들어낸다.

즉 같은 query key를 가지지만 각자 새로운 query이며 각각 서로 다른 cache time과 stale time을 가지고 있으며, 완전 서로 다른 것으로 취급된다.

이 같은 상황은 react-query devtools를 통해 훨씬 쉽게 이해할 수 있다.

실제 사용예시

같은 query key에 뒤의 인자가 다른 서로 다른 cache data가 있음을 확인할 수 있다.
또한 제일 최신인 5번 데이터만이 stale 상태이고 나머지는 모두 inactive 상태임을 확인할 수 있다.
그리고 inactive한 data는 cache time이 남아있는 한에서 다시 쓸 수 있는 data이며, 이 데이터를 다시 사용하게 되면 곧바로 stale 상태가 되며 기존에 사용하던 데이터는 다시 inactive 상태가 된다.

profile
최선을 다한다는 것은 할 수 있는 한 가장 핵심을 향한다는 것

0개의 댓글