From 5aa98b0bda5c01712f9e6a967b8a3b5328286e01 Mon Sep 17 00:00:00 2001 From: manNomi Date: Sat, 24 Jan 2026 00:28:56 +0900 Subject: [PATCH 1/2] =?UTF-8?q?fix:=20react=20query=20=EC=9E=AC=EC=8B=9C?= =?UTF-8?q?=EB=8F=84=201=ED=9A=8C=20=EC=A0=9C=ED=95=9C=20=EB=B0=8F=20?= =?UTF-8?q?=EB=A1=9C=EB=94=A9=20ux=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - react query 재시도 횟수를 3회에서 1회로 제한 - query 실패 시 전역 에러 토스트 추가 (401 제외) - 로딩 스피너에 반투명 배경 및 cursor-wait 추가로 인터랙션 차단 - ScorePageContent의 retry: false 옵션 제거하여 전역 설정 적용 --- .../application/ScorePageContent.tsx | 4 +-- .../GlobalLayout/ui/ClientModal/index.tsx | 2 +- src/lib/react-query/queryClient.ts | 34 +++++++++++++------ 3 files changed, 25 insertions(+), 15 deletions(-) diff --git a/src/app/university/application/ScorePageContent.tsx b/src/app/university/application/ScorePageContent.tsx index 0991f75d..bda0869a 100644 --- a/src/app/university/application/ScorePageContent.tsx +++ b/src/app/university/application/ScorePageContent.tsx @@ -47,9 +47,7 @@ const ScorePageContent = () => { data: scoreResponseData = initialData, isError, isLoading, - } = useGetApplicationsList({ - retry: false, - }); + } = useGetApplicationsList(); const filteredAndSortedData = useMemo(() => { // ✨ 1. 대학 이름(koreanName)을 기준으로 중복을 제거하는 헬퍼 함수 diff --git a/src/components/layout/GlobalLayout/ui/ClientModal/index.tsx b/src/components/layout/GlobalLayout/ui/ClientModal/index.tsx index 92ade71c..41dd2ef8 100644 --- a/src/components/layout/GlobalLayout/ui/ClientModal/index.tsx +++ b/src/components/layout/GlobalLayout/ui/ClientModal/index.tsx @@ -33,7 +33,7 @@ const ClientModal = () => { return ( <> {isFetching ? ( -
+
) : null} diff --git a/src/lib/react-query/queryClient.ts b/src/lib/react-query/queryClient.ts index 8d18bf17..4a42d8ed 100644 --- a/src/lib/react-query/queryClient.ts +++ b/src/lib/react-query/queryClient.ts @@ -1,9 +1,30 @@ import type { AxiosError } from "axios"; import { toast } from "@/lib/zustand/useToastStore"; -import { QueryClient } from "@tanstack/react-query"; +import { MutationCache, QueryCache, QueryClient } from "@tanstack/react-query"; const queryClient = new QueryClient({ + queryCache: new QueryCache({ + onError: (error) => { + // query 실패 시 전역 에러 토스트 (401 제외) + const axiosError = error as AxiosError<{ message?: string }>; + const status = axiosError?.response?.status; + if (status === 401) return; // 인증 오류는 토스트 표시 X + + const errorMessage = + axiosError?.response?.data?.message || axiosError?.message || "오류가 발생했습니다. 다시 시도해주세요."; + toast.error(errorMessage); + }, + }), + mutationCache: new MutationCache({ + onError: (error) => { + // mutation 실패 시 전역 에러 토스트 + const axiosError = error as AxiosError<{ message?: string }>; + const errorMessage = + axiosError?.response?.data?.message || axiosError?.message || "오류가 발생했습니다. 다시 시도해주세요."; + toast.error(errorMessage); + }, + }), defaultOptions: { queries: { staleTime: 5 * 60 * 1000, // 데이터 신선도(5분) @@ -11,19 +32,10 @@ const queryClient = new QueryClient({ retry: (failureCount, error) => { const status = (error as AxiosError | undefined)?.response?.status; if (status === 401) return false; // 인증 오류는 재시도 X - return failureCount < 3; // 그 외에는 최대 3회까지 재시도 + return failureCount < 1; // 그 외에는 최대 1회까지 재시도 }, refetchOnWindowFocus: false, // 창 포커스 복귀 시 refetch 비활성 }, - mutations: { - onError: (error) => { - // mutation 실패 시 전역 에러 토스트 - const axiosError = error as AxiosError<{ message?: string }>; - const errorMessage = - axiosError?.response?.data?.message || axiosError?.message || "오류가 발생했습니다. 다시 시도해주세요."; - toast.error(errorMessage); - }, - }, }, }); From b2d50d7140b01f6952e28e2d1e6b331bfb2937dd Mon Sep 17 00:00:00 2001 From: manNomi Date: Sat, 24 Jan 2026 00:48:42 +0900 Subject: [PATCH 2/2] =?UTF-8?q?refactor=20:=20=ED=94=84=EB=A6=AC=ED=8B=B0?= =?UTF-8?q?=EC=96=B4=20=ED=8F=AC=EB=A7=B7=ED=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/university/application/ScorePageContent.tsx | 6 +----- src/components/layout/GlobalLayout/ui/ClientModal/index.tsx | 6 +++++- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/app/university/application/ScorePageContent.tsx b/src/app/university/application/ScorePageContent.tsx index bda0869a..d071d907 100644 --- a/src/app/university/application/ScorePageContent.tsx +++ b/src/app/university/application/ScorePageContent.tsx @@ -43,11 +43,7 @@ const ScorePageContent = () => { thirdChoice: [], }; - const { - data: scoreResponseData = initialData, - isError, - isLoading, - } = useGetApplicationsList(); + const { data: scoreResponseData = initialData, isError, isLoading } = useGetApplicationsList(); const filteredAndSortedData = useMemo(() => { // ✨ 1. 대학 이름(koreanName)을 기준으로 중복을 제거하는 헬퍼 함수 diff --git a/src/components/layout/GlobalLayout/ui/ClientModal/index.tsx b/src/components/layout/GlobalLayout/ui/ClientModal/index.tsx index 41dd2ef8..957e2246 100644 --- a/src/components/layout/GlobalLayout/ui/ClientModal/index.tsx +++ b/src/components/layout/GlobalLayout/ui/ClientModal/index.tsx @@ -33,7 +33,11 @@ const ClientModal = () => { return ( <> {isFetching ? ( -
+
) : null}