본문 바로가기
Front-end

[React] Tanstack query 키 관리하기 in QueryKey-Factory

by ghDev 2024. 7. 18.

 

 

이번엔 아트인포 에서 Next.js와 Tanstack Query를 사용하며 키 관리를 어떻게 했는지 정리해봤습니다.

 

키 관리가 필요한 이유..?

Tanstack-Query가 제공하는 기능들을 제대로 사용하기 위해서는 필수적으로 이해해야 하는 개념들이 몇 가지 존재합니다. 오늘 다뤄볼 주제는 그 핵심 개념들 중 하나인 Query Keys를 관리하는 방법.

 

공식문서에서는 다음과 같이 Query Keys를 소개한다.

 


At its core, TanStack Query manages query caching for you based on query keys. Query keys have to be an Array at the top level, and can be as simple as an Array with a single string, or as complex as an array of many strings and nested objects. As long as the query key is serializable, and unique to the query's data, you can use it!

https://tanstack.com/query/latest/docs/framework/react/guides/query-keys

 

Tanstack Query는 Query Key를 기반으로 Query Caching을 관리한다.

제대로 관리가 되지 못하는 경우 의도하지 않은 문제가 발생 할 수 있고 여러 관리 방법들이 존재한다.

그 중 Query Key Factories를 사용한 관리 방법에 대해 설명해본다.

 

/lib/queries.ts

const jobs = createQueryKeys("jobs", {
  detail: (jobId: number) => ({
    queryKey: [jobId],
    queryFn: () => getJob(jobId),
  }),
  list: (filters: JobsRequest) => ({
    queryKey: ["list", { filters }],
    queryFn: () => getJobs(filters),
  }),
  infiniteList: (filters: JobsRequest) => ({
    queryKey: ["infiniteList", { filters }],
    queryFn: ({ pageParam }: { pageParam: number }) =>
      getInfiniteJobs({ ...filters, page: pageParam }),
  }),
  count: () => ({
    queryKey: ["count"],
    queryFn: getJobsCount,
  }),
})

 

예시로 아트인포의 채용에서 사용되는 코드를 가져왔습니다.

 

채용 리스트와 상세, 갯수 조회 api를 포함하고 있습니다.

어떻게 사용할까요?

 

// 일반 useQuery 상세페이지 조회
const { data } = useQuery({
    queryKey: ["jobs", jobId],
    queryFn: () => getJob(jobId),
  })


// 키값을 관리했을때 상세페이지 조회
  const { data } = useQuery(queries.jobs.detail(jobId))
  
 
// 해당 채용글이 변경되어 갱신이 필요하다면?

const handledeleteJob = async () => {
  await deleteJob(jobId)
  await queryClient.invalidateQueries({
    queryKey: queries.jobs._def,
  })
}

 

이런식으로 쓰일수 있습니다.

queries.jobs._def 는 무슨 값일까요?

 

위에서 선언했던 jobs createQueryKeys의 첫번째 인자가 들어있습니다.

 


  queryClient.invalidateQueries({
    queryKey: ["jobs"],
  })

 

 

이렇게 들어가게되겠죠

"jobs" Query Key를 무효화시킨다는것은 ["jobs", "list", filter], ["jobs", "infiniteList", filter] 등

Query Key에 "jobs"가 들어간 모든 캐싱데이터를 무효화시켜주게됩니다.

실제 사용 예시:)

 

//news/page.tsx

 const {
    data: newsList,
    hasNextPage,
    fetchNextPage,
  } = useSuspenseInfiniteQuery<ScrollApiResponse<NEWS, "news">>({
    ...queries.news.infiniteList(queryParams),
    initialPageParam: 1,
    getNextPageParam: lastPage => {
      if (!lastPage.isLast) return lastPage.nextPage
      return null
    },
  })


// hooks/useMutation.ts

  const handleDelete = async (id?: number) => {
    if (!deleteFn) return

    try {
      await startTransition(deleteFn(id))
      successToast(successMessage?.delete || "삭제되었습니다.")
      router.push(redirectPath)
      queryClient.invalidateQueries({
        queryKey,
      })
    } catch (error: any) {
      errorToast(error.message)
      console.error(error)
    }
  }

 

Tanstack Query를 사용하기 시작한지 얼마 안되었을땐 데이터 갱신 시점을 못찾기도 하고 어떤 데이터를 갱신해야 하는지

 

도 모르는 경우가 있었습니다.

심지어 queryKey 오타로 데이터 갱신이 안되었고 몇시간동안 원인을 못찾은 경우도 있었습니다.

 

지금은 가볍게 사용중이지만 추후 프로젝트가 커질 경우 더 간결하게 적용하여 정리해보겠습니다.

 



출처: https://www.youtube.com/watch?v=nkXIpGjVxWU

 

출처: https://github.com/lukemorales/query-key-factory

 

GitHub - lukemorales/query-key-factory: A library for creating typesafe standardized query keys, useful for cache management in

A library for creating typesafe standardized query keys, useful for cache management in @tanstack/query - lukemorales/query-key-factory

github.com