본문 바로가기

TIL

TIL - 트러블 슈팅 with tanstack/react-query

문제점

내일배움캠프 과제로 인한 코딩 중 API 호출이 성공적으로 작동하지 않았습니다. 새로운 지출 항목을 생성하려고 했으나, 데이터가 제대로 반영되지 않고 UI에도 나타나지 않았습니다.

 

원인 분석

  1. 에러 처리가 부족: API 호출 시 발생하는 에러를 처리하지 않아서 문제를 진단하기 어려웠습니다.
  2. 로그 부족: API 호출 전후로 충분한 로그가 없어서 데이터 흐름을 추적하기 어려웠습니다.
  3. React Query 설정 누락: useMutation 훅에서 onSuccess와 onError 옵션이 누락되어 API 호출 후의 후속 처리가 제대로 이루어지지 않았습니다.

 

해결 방안 단계

  1. 에러 처리 추가: API 호출 시 발생하는 에러를 try-catch 블록을 통해 처리하고, 콘솔에 에러 로그를 출력하도록 했습니다.
  2. 로그 추가: API 호출 전후로 로그를 추가하여 데이터 흐름을 추적하고, 문제가 발생하는 지점을 정확히 파악할 수 있도록 했습니다.
  3. React Query 설정 업데이트: useMutation 훅에서 onSuccess와 onError 옵션을 추가하여, API 호출이 성공하거나 실패했을 때 적절한 후속 처리를 할 수 있도록 했습니다.

 

결정적인 해결 방안

  • Mutation 옵션 사용: onSuccess 옵션을 추가하여 API 호출이 성공한 후, queryClient.invalidateQueries(["expenses"])를 호출하여 expenses 쿼리를 무효화하고, 데이터를 다시 가져오도록 했습니다. 이를 통해 새로운 데이터가 즉시 UI에 반영되었습니다.

onSuccess의 역할

onSuccess의 역할이 컸던 이유데이터 변경 후의 후속 처리(예: 캐시 무효화, 사용자에게 성공 메시지 표시 등)가 제대로 설정되지 않으면, 데이터가 변경되더라도 UI가 이를 반영하지 않거나, 캐시된 오래된 데이터가 계속해서 사용될 수 있기 때문입니다. 따라서 onSuccess를 통해 성공적으로 데이터를 처리한 후 필요한 후속 처리를 명확히 정의함으로써 이 문제를 해결할 수 있었습니다.

 

코드 예시

// 변경 전
async getExpenses() {
    const response = await this.#client.get("/expenses");
    console.log("응답 데이터:", response.data);
    return response.data;
  }

export const useGetExpenses = () => {
  const queryClient = useQueryClient();
  return useQuery({
    queryKey: ["expenses"],
    queryFn: api.expense.getExpenses,
    onSuccess: () => queryClient.invalidateQueries(["expenses"]),
  });
};

function onSubmit(newExpense) {
  console.log(newExpense);
  createExpense(newExpense);
  toast.success("등록되었습니다.");
  setExpense(initialExpense);
}

--------------------------------------------------------------
// 디버깅 하면서 바뀐 코드 

async getExpenses() {
    try {
      const response = await this.#client.get("/expenses");
      console.log("응답 데이터:", response.data);
      return response.data;
    } catch (error) {
      console.error("지출 데이터를 가져오는 중 오류 발생:", error);
      throw error;
    }
  }
  
  export const useGetExpenses = () => {
  const queryClient = useQueryClient();
  return useQuery({
    queryKey: ["expenses"],
    queryFn: async () => {
      const data = await api.expense.getExpenses();
      console.log("Fetched expenses data:", data);
      return data;
    },
    onSuccess: () => queryClient.invalidateQueries(["expenses"]),
  });
};
  
 function onSubmit(newExpense) {
    console.log("Submitting new expense:", newExpense);
    createExpense(newExpense, {
      onSuccess: () => {
        toast.success("등록되었습니다.");
        setExpense(initialExpense);
      },
      onError: (error) => {
        toast.error("등록 실패: " + error.message);
      }
    });
  }

 

 

결론

React Query의 useMutation 훅에서 onSuccess 옵션을 추가하여, 성공적으로 데이터가 생성된 후 자동으로 쿼리를 무효화하고 데이터를 다시 가져오도록 설정함으로써 문제가 해결되었습니다. 이로 인해 새로운 데이터가 UI에 즉시 반영되었습니다.

 

배운 점

  • React Query의 useMutation 훅에서 onSuccess 옵션을 사용하여 데이터 변경 후의 후속 처리를 명확하게 설정하는 것이 중요합니다.
  • 충분한 로그와 에러 처리를 통해 문제를 빠르게 진단하고 해결할 수 있습니다.