🔥 임시 데이터(Placeholder Query Data)로 쿼리 결과 미리 채우기

406자
5분

임시 데이터란 무엇인가?

임시 데이터를 사용하면 실제 데이터를 가져오는 동안 쿼리가 이미 데이터를 갖고 있는 것처럼 동작할 수 있습니다. 이는 initialData 옵션과 비슷하지만, 중요한 차이점이 있습니다. 임시 데이터는 캐시에 저장되지 않습니다. 이 기능은 실제 데이터를 가져오는 동안 부분적인 데이터나 가짜 데이터로 쿼리를 성공적으로 렌더링할 수 있는 상황에서 유용합니다.

예를 들어, 개별 블로그 게시물 쿼리에서 게시물 목록의 "미리보기" 데이터를 활용할 수 있습니다. 이 미리보기 데이터는 제목과 본문의 일부만 포함합니다. 이 부분적인 데이터를 개별 쿼리 결과에 영구적으로 저장하고 싶지는 않겠지만, 실제 쿼리가 전체 객체를 가져오는 동안 컨텐츠 레이아웃을 최대한 빨리 보여주는 데 도움이 됩니다.

쿼리에 임시 데이터를 제공하는 방법은 크게 두 가지가 있습니다:

  1. 선언적 방법:
    • 쿼리에 placeholderData를 제공하여 캐시가 비어 있을 때 미리 채웁니다.
  2. 명령적 방법:
    • queryClient를 사용하여 placeholderData 옵션과 함께 데이터를 미리 가져오거나 가져옵니다.

임시 데이터를 사용하면 쿼리가 대기 상태에 있지 않습니다. 대신 성공 상태로 시작합니다. 표시할 데이터가 있기 때문입니다. 비록 그 데이터가 "임시" 데이터일지라도 말입니다. 이 임시 데이터를 "실제" 데이터와 구별하기 위해 쿼리 결과에 isPlaceholderData 플래그가 true로 설정됩니다.

값으로 임시 데이터 사용하기

function Todos() {
  const result = useQuery({
    queryKey: ['todos'],
    queryFn: () => fetch('/todos'),
    placeholderData: placeholderTodos,
  })
}
 
typescript

임시 데이터 메모이제이션

쿼리의 임시 데이터에 접근하는 과정이 복잡하거나 매 렌더링마다 수행하고 싶지 않다면, 값을 메모이제이션할 수 있습니다:

function Todos() {
  const placeholderData = useMemo(() => generateFakeTodos(), [])
  const result = useQuery({
    queryKey: ['todos'],
    queryFn: () => fetch('/todos'),
    placeholderData,
  })
}
 
typescript

함수로 임시 데이터 사용하기

placeholderData는 함수로도 사용할 수 있습니다. 이 함수는 이전에 성공한 쿼리의 데이터와 메타 정보에 접근할 수 있습니다. 이 방법은 한 쿼리의 데이터를 다른 쿼리의 임시 데이터로 사용하고 싶을 때 유용합니다. 쿼리 키가 변경될 때(예: ['todos', 1]에서 ['todos', 2]로), 새 데이터를 가져오는 동안 로딩 스피너를 보여주는 대신 "이전" 데이터를 계속 표시할 수 있습니다.

const result = useQuery({
  queryKey: ['todos', id],
  queryFn: () => fetch(`/todos/${id}`),
  placeholderData: (previousData, previousQuery) => previousData,
})
 
typescript

캐시에서 임시 데이터 가져오기

때로는 다른 쿼리의 캐시된 결과에서 임시 데이터를 제공할 수 있습니다. 좋은 예로, 블로그 게시물 목록 쿼리의 캐시된 데이터에서 게시물의 미리보기 버전을 찾아 개별 게시물 쿼리의 임시 데이터로 사용할 수 있습니다:

function Todo({ blogPostId }) {
  const queryClient = useQueryClient()
  const result = useQuery({
    queryKey: ['blogPost', blogPostId],
    queryFn: () => fetch(`/blogPosts/${blogPostId}`),
    placeholderData: () => {
      // 'blogPosts' 쿼리에서 이 blogPost 쿼리의 임시 데이터로
      // 더 작은/미리보기 버전의 blogPost를 사용합니다
      return queryClient
        .getQueryData(['blogPosts'])
        ?.find((d) => d.id === blogPostId)
    },
  })
}
 
typescript

추가 정보

임시 데이터와 초기 데이터의 차이점을 비교하려면 커뮤니티 리소스를 참고하세요.