쿼리 무효화 & refetchType

hyeryeon·2024년 9월 3일

React

목록 보기
16/19

쿼리... 란 ????
"쿼리"라는 용어는 데이터베이스나 API와 같은 외부 데이터 소스로부터 데이터를 가져오거나 조회하는 요청을 의미합니다.
React Query에서의 쿼리: 리액트 쿼리에서는 "쿼리"가 서버에 데이터를 요청하는 작업을 의미합니다. 이 쿼리는 특정 키(query key)로 식별됩니다. 예를 들어, useQuery(['events'], fetchEvents)와 같은 코드를 사용하면 ['events']라는 쿼리 키로 이벤트 데이터를 서버에서 가져오는 작업을 수행합니다.

쿼리 무효화(Query Invalidation)

사용자가 새로운 이벤트를 추가했을 때, 현재 화면에 표시된 이벤트 목록이 즉시 업데이트되지 않으면, 사용자는 방금 추가한 이벤트를 확인할 수 없다.
이러한 경우, React Query의 쿼리 무효화 기능을 통해 데이터의 일관성을 유지할 수 있다!

새 이벤트를 생성해도 Recently added events 섹션에 바로 반영되지 않는 이유는,
-> React Query가 데이터를 다시 가져오지 않기 때문

페이지를 이동했다가 돌아오면 React Query가 데이터를 다시 가져오게 되지만, 데이터가 변경된 것이 확실한 경우 즉시 데이터를 업데이트하고 싶다.

그럴땐 , queryClient.invalidateQueries를 사용해 특정 쿼리를 무효화하자
이것을 통해 React Query는 해당 쿼리에 연결된 데이터를 다시 가져오게 된당

쿼리 무효화(query invalidation)는
리액트 쿼리(React Query)에서 특정 데이터를 다시 가져와야 한다고 명시하는 작업입니다. 즉, 무효화된 쿼리는 더 이상 최신 상태가 아니므로, 리액트 쿼리가 해당 데이터를 새로 가져오도록 요청하게 만듭니다.

queryClient.invalidateQueries

queryClient.invalidateQueries는 특정 쿼리를 무효화하는 데 사용됨
이 함수가 호출되면, 해당 쿼리는 "오래된 데이터"로 표시되고, React Query는 해당 쿼리의 데이터를 다시 가져오게 된다.

import { queryClient } from '../../util/http.js';

queryClient.invalidateQueries({ queryKey: ['events'] });
  • queryKey: 무효화할 쿼리를 식별하는 키
  • 쿼리 키는 배열 형태로 정의되며, ['events']와 같은 형태로 사용됨
    이 키는 React Query가 해당 데이터를 가져올 때 사용한 쿼리 키와 일치해야 함

쿼리 키의 중요성

쿼리 키는 데이터를 식별하는 중요한 요소!
React Query에서 데이터를 가져올 때 쿼리 키를 기준으로 캐시된 데이터를 관리한다.

  • 쿼리 키가 ['events']로 지정된 모든 쿼리가 무효화되면, 해당 쿼리 키를 사용해 데이터를 가져온 모든 컴포넌트가 영향을 받게 된다.

  • 쿼리 키는 배열로 구성되며, 배열의 첫 번째 요소는 일반적으로 엔티티의 이름(예: events)이고, 추가 요소는 해당 데이터를 가져오기 위한 조건이나 식별

exact 옵션

invalidateQueries 함수에는 exact 옵션이 있다.
이 옵션을 사용하면, 쿼리 키가 정확히 일치하는 경우에만 쿼리를 무효화할 수 있다.

예를 들어, exact: true로 설정하면, ['events']라는 쿼리 키를 가진 쿼리만 무효화되고, ['events', { id: 1 }]와 같은 쿼리 키를 가진 쿼리는 무효화되지 않는다

  • exact: false (기본값): 전달한 쿼리 키와 일부라도 일치하는 모든 쿼리를 무효화
  • exact: true: 전달한 쿼리 키와 정확히 일치하는 쿼리만 무효화

1. exact: false (기본값)

queryClient.invalidateQueries({ queryKey: ['events'] });

이 코드는 쿼리 키가 ['events']와 부분적으로라도 일치하는 모든 쿼리를 무효화한다.
예를 들어:

['events']
['events', 'upcoming']
['events', { id: 123 }]

위의 모든 쿼리 키를 가진 쿼리들이 무효화된다. 즉, ['events']라는 문자열이 포함된 모든 쿼리가 무효화 대상

2. exact: true


queryClient.invalidateQueries({ queryKey: ['events'], exact: true });

이 코드는 쿼리 키가 정확히 ['events']와 일치하는 쿼리만 무효화합니다.
즉:
['events']는 무효화!

하지만 ['events', 'upcoming'] 또는 ['events', { id: 123 }] 등은 무효화되지 않는다.

왜 exact를 사용하는가?

  • 특정 쿼리만 무효화하고 싶을 때 사용
    예를 들어, ['events']라는 쿼리는 무효화하고 싶지만, ['events', 'upcoming']처럼 세부적으로 다른 쿼리는 그대로 두고 싶다면 exact: true를 설정하면 됨!
  • 기본적으로 exact: false로 설정되어 있어 여러 쿼리가 무효화될 수 있다. 그러나 데이터의 일부분만 변경되었고, 다른 연관 데이터는 그대로 두고 싶은 경우 exact: true로 설정해 불필요한 재로딩을 방지할 수 있습니다.

이벤트 삭제 후 404 오류

문제 상황

이벤트 삭제 후 404 오류

사용자가 이벤트 세부 정보 페이지에서 특정 이벤트를 삭제한 후, 뒤로 이동하면 404 요청이 발생하는 문제가 생겼다
삭제된 이벤트의 세부 정보를 다시 가져오려는 쿼리가 실행되기 때문에 발생ㅏ하는데
삭제 후에도 여전히 사용자가 세부 정보 페이지에 있기 때문에, 리액트 쿼리가 이 페이지의 데이터를 다시 가져오려고 시도하며, 이때 삭제된 이벤트에 대한 요청이 실패하여 404 오류가 발생한다....

해결 방법

invalidateQueries의 refetchType 옵션 사용

invalidateQueries 메소드에 refetchType: 'none' 옵션을 추가하여, 무효화된 쿼리가 자동으로 다시 실행되지 않도록 설정하자

이 설정을 통해 해당 쿼리는 무효화되지만, 즉시 다시 데이터를 가져오지는 않습니다. 대신, 다음번에 해당 쿼리가 필요할 때 다시 실행됩니다.

const {mutate} = useMutation({
    mutationFn:deleteEvent,
    onSuccess:() => {
      queryClient.invalidateQueries({
        queryKey:['events'],
        ⭐refetchType:'none'
      })
      navigate('/events');
    }
  });

적용하고 나면

  • 이벤트를 삭제하고 난 후, 세부 정보 페이지에서 더 이상 자동으로 다시 가져오지 않기 때문에, 404 오류가 발생하지 않습니다.
  • 사용자가 모든 이벤트 페이지로 이동하면, 그 페이지의 쿼리가 다시 트리거되어 최신 이벤트 목록을 가져오게 됩니다.

0개의 댓글