본문 바로가기
Web Study/Next.js

fetch 와 react-query 캐싱

by 쿠리의일상 2024. 3. 14.

문제점?

넥스트 14 버전을 사용하고 있다. 그 옵션 속성들 중에서도 cache 에 대한 정리가 필요할 것 같아서 작성한다.

넥스트는 fetch 를 사용할 것을 권장하고 있다. 기존의 리액트 프로젝트에서 axios 를 사용하던 나는 권장 사용법대로 사용할 수밖에... 근데 현재 만들고 있는 프로토타입 프로젝트에서 자꾸 이전 캐싱된 정보가 fetch 되는 것 아닌가? 리액트 쿼리의 문제인지 넥스트의 문제인지 아직은 잘 모르겠어서 차근히 정리하고자 한다.

 

현상황

 로그인을 하면 -> 그 회원이 포함된 리스트에 해당하는 정보가 보여야 하는 상황이다. 하지만 기존의 로그인에서 다른 사용자로 로그인을 하면 바로 전의 로그인한 사람의 리스트가 보인다. 매번 db 를 읽어와서 처리해주면 된다고 생각했는데 캐싱된 정보가 보이는 거 보니 리액트 쿼리의 문제일 것 같다.

 

cache?

넥스트에선 매 요청마다 동적인 데이터를 얻고자 할 때 cache 속성을 no-store 로 지정해주면 된다고 했다. 하지만 안타깝게도 내 플젝에는 소용없었다.

export async function fetchList() {
  const response = await fetch(`${baseUrl}/worklist/list`, {
    method: "Get",
    credentials: "include",
    cache: "no-store",
    headers: { Cookie: cookies().toString() },
    next: {
      tags: ["lists", "list"],
    },
  });
  return await response.json();
}

그럼 이 fetch 문을 불러오는 리액트 쿼리의 문제일 것 같았다.

사실 넥스트 13 이후의 fetch 에선 캐싱 기능이 향상되었다고 알고 있었고 그래서 굳이 리액트 쿼리가 필요 없지 않나 생각한 적도 있었지만 프로젝트가 커지면서 최적화 문제에 다다르기 전 초기부터 리액트 쿼리를 적용하는 것이 좋겠다고 판단하였다. 현재 프로젝트에선 리액트 쿼리와 저스탠드를 사용하고 있다.

 

리액트 쿼리에서 캐싱

queryClient의 싱글톤 객체를 prefetchQuery 나 fetchQuery 로 사용하는 방식과 useQuery 방식이 있다. 

https://tanstack.com/query/latest/docs/reference/QueryClient#queryclientrefetchqueries

 

QueryClient | TanStack Query Docs

 

tanstack.com

prefetchQuery 나 fetchQuery 는 서버에서 미리 받아온 데이터를 캐싱해주는 기능이 있었던 것이다. 그래서 useQuery 로 바꿔줄 필요성을 느꼈다. 하지만 내 세션을 읽어오는 fetch 문 중 하나가 cookies 를 사용하기에 use client 와 함께 사용할 수 없다는 사실을 알게 되었다.

현재는 로그인하면 서버에서 세션을 부여받고 세션아이디를 받아서 쿠키에 저장 -> 로그인이 필요한 페이지에 접근할 때마다 해당 세션아이디 (쿠키) 를 확인 ... 요렇게 해주고 있었다.

이 문제를 어떻게 해결해야 할지 감이 오지 않아서 하루를 꼬박 날렸다.

해결은 언제나 간단하게...

const queryClient = new QueryClient();
await queryClient.prefetchQuery({
    queryKey: ["dbs", "dblist"],
    queryFn: fetchList,
    staleTime: 0,
  });
  const dehydratedState = dehydrate(queryClient);
  
// 정보를 불러올 때
const resultlist = queryClient.getQueryData(["dbs", "dblist"]).dblist;

어이없게도 옵션을 줄 수 있었다(..) 저렇게 주니 로그아웃 후 다른 계정으로 로그인하면 바로 refetching 되었다. 나처럼 useQuery 를 사용할 수 없는 경우에 이렇게 처리해주면 될 것 같다. 물론 이렇게 처리해주면 동일한 아이디로 로그인해주면 fetchList 가 실행되지 않으므로 최적화가 되어 있다고 판단된다.