From 1f87b9dd5e07dc4c1333274718f7a452d7b6be8c Mon Sep 17 00:00:00 2001 From: cloud0406 Date: Wed, 15 Jan 2025 13:25:11 +0900 Subject: [PATCH 01/16] =?UTF-8?q?=E2=9C=A8[Feat]=20=EC=97=90=EB=9F=AC=20?= =?UTF-8?q?=EB=B0=94=EC=9A=B4=EB=8D=94=EB=A6=AC=20=EB=B0=8F=20=ED=95=B8?= =?UTF-8?q?=EB=93=A4=EB=A7=81=20wrapper=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/ErrorBoundary.tsx | 64 ++++++++++++++++++++++++++++ src/app/ErrorFallback.tsx | 24 +++++++++++ src/app/ErrorHandlingWrapper.tsx | 27 ++++++++++++ src/lib/utils/reactQueryProvider.tsx | 4 ++ 4 files changed, 119 insertions(+) create mode 100644 src/app/ErrorBoundary.tsx create mode 100644 src/app/ErrorFallback.tsx create mode 100644 src/app/ErrorHandlingWrapper.tsx diff --git a/src/app/ErrorBoundary.tsx b/src/app/ErrorBoundary.tsx new file mode 100644 index 00000000..4095ccfa --- /dev/null +++ b/src/app/ErrorBoundary.tsx @@ -0,0 +1,64 @@ +'use client'; + +import { Component, ReactNode, ErrorInfo, ComponentType } from 'react'; + +interface ErrorBoundaryState { + hasError: boolean; + error: Error | null; +} + +export interface FallbackProps { + error: Error | null; + resetErrorBoundary: () => void; +} + +interface ErrorBoundaryProps { + FallbackComponent: ComponentType; + onReset: () => void; + children: ReactNode; +} + +class ErrorBoundary extends Component { + constructor(props: ErrorBoundaryProps) { + super(props); + this.state = { + hasError: false, + error: null, + }; + this.resetErrorBoundary = this.resetErrorBoundary.bind(this); + } + + static getDerivedStateFromError(error: Error): ErrorBoundaryState { + return { hasError: true, error }; + } + + componentDidCatch(error: Error, errorInfo: ErrorInfo): void { + console.error('ErrorBoundary caught an error:', error, errorInfo); + } + + resetErrorBoundary(): void { + this.props.onReset(); + this.setState({ + hasError: false, + error: null, + }); + } + + render() { + const { hasError, error } = this.state; + const { FallbackComponent, children } = this.props; + + if (hasError && error) { + return ( + + ); + } + + return children; + } +} + +export default ErrorBoundary; diff --git a/src/app/ErrorFallback.tsx b/src/app/ErrorFallback.tsx new file mode 100644 index 00000000..6bb3506b --- /dev/null +++ b/src/app/ErrorFallback.tsx @@ -0,0 +1,24 @@ +'use client'; + +import { FallbackProps } from './ErrorBoundary'; + +export default function ErrorFallback({ + error, + resetErrorBoundary, +}: FallbackProps) { + return ( +
+

오류가 발생했습니다

+

{error?.message}

+ +
+ ); +} diff --git a/src/app/ErrorHandlingWrapper.tsx b/src/app/ErrorHandlingWrapper.tsx new file mode 100644 index 00000000..921df7bf --- /dev/null +++ b/src/app/ErrorHandlingWrapper.tsx @@ -0,0 +1,27 @@ +'use client'; + +import { QueryErrorResetBoundary } from '@tanstack/react-query'; +import { ComponentType, ReactNode, Suspense } from 'react'; +import ErrorBoundary, { FallbackProps } from './ErrorBoundary'; + +interface ErrorHandlingWrapperProps { + children: ReactNode; + fallbackComponent: ComponentType; + suspenseFallback: ReactNode; +} + +export default function ErrorHandlingWrapper({ + children, + fallbackComponent: FallbackComponent, + suspenseFallback, +}: ErrorHandlingWrapperProps) { + return ( + + {({ reset }) => ( + + {children} + + )} + + ); +} diff --git a/src/lib/utils/reactQueryProvider.tsx b/src/lib/utils/reactQueryProvider.tsx index 28efda55..c977b961 100644 --- a/src/lib/utils/reactQueryProvider.tsx +++ b/src/lib/utils/reactQueryProvider.tsx @@ -12,6 +12,10 @@ export const queryClient = new QueryClient({ retryOnMount: false, // 마운트 시 실패한 쿼리 재시도 여부 staleTime: 1000 * 60 * 5, // 데이터가 'fresh'한 상태로 유지되는 시간 (5분) gcTime: 1000 * 60 * 10, // 사용하지 않는 캐시 데이터가 메모리에서 제거되기까지의 시간 (10분) + throwOnError: true, + }, + mutations: { + throwOnError: true, }, }, }); From fa64e1f22558a1e215f72d339ad81b57218a35ea Mon Sep 17 00:00:00 2001 From: cloud0406 Date: Wed, 15 Jan 2025 15:19:37 +0900 Subject: [PATCH 02/16] =?UTF-8?q?=E2=99=BB=EF=B8=8F[Refactor]=20=EC=9C=A0?= =?UTF-8?q?=EC=A0=80=20=EC=A0=95=EB=B3=B4=20=ED=9B=85=20enabled=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/lib/hooks/useGetUserByPath.ts | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/lib/hooks/useGetUserByPath.ts b/src/lib/hooks/useGetUserByPath.ts index 4130acf0..caf30db4 100644 --- a/src/lib/hooks/useGetUserByPath.ts +++ b/src/lib/hooks/useGetUserByPath.ts @@ -4,15 +4,14 @@ import { usePathname } from 'next/navigation'; export function useGetUserByPath() { const pathname = usePathname(); - const userId = Number(pathname?.split('/')[2]); + const userId = pathname?.split('/')[2]; + + const isValidUserId: boolean = Boolean(userId && !isNaN(Number(userId))); - const { queryKey, queryFn } = users.userInfo(userId); const { data } = useQuery({ - queryKey, - queryFn, + ...users.userInfo(Number(userId)), + enabled: isValidUserId, }); - const user = data?.data; - - return user; + return data?.data; } From 75a342c274881851af389a77b77f5b70f3ef97ae Mon Sep 17 00:00:00 2001 From: cloud0406 Date: Wed, 15 Jan 2025 15:19:54 +0900 Subject: [PATCH 03/16] =?UTF-8?q?=E2=9C=A8[Feat]=20=EB=82=B4=EA=B0=80=20?= =?UTF-8?q?=EC=B0=B8=EC=97=AC=ED=95=9C=20=EB=AA=A8=EC=9E=84=20=EC=97=90?= =?UTF-8?q?=EB=9F=AC=EB=B0=94=EC=9A=B4=EB=8D=94=EB=A6=AC=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/ErrorBoundary.tsx | 18 +++++++++++++----- .../profile/container/ClubContents.tsx | 12 +++++++++++- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/src/app/ErrorBoundary.tsx b/src/app/ErrorBoundary.tsx index 4095ccfa..99104570 100644 --- a/src/app/ErrorBoundary.tsx +++ b/src/app/ErrorBoundary.tsx @@ -12,32 +12,37 @@ export interface FallbackProps { resetErrorBoundary: () => void; } -interface ErrorBoundaryProps { +type ErrorBoundaryProps = { FallbackComponent: ComponentType; onReset: () => void; children: ReactNode; -} +}; class ErrorBoundary extends Component { constructor(props: ErrorBoundaryProps) { super(props); + this.state = { hasError: false, error: null, }; + this.resetErrorBoundary = this.resetErrorBoundary.bind(this); } + /** 에러 상태 변경 */ static getDerivedStateFromError(error: Error): ErrorBoundaryState { return { hasError: true, error }; } componentDidCatch(error: Error, errorInfo: ErrorInfo): void { - console.error('ErrorBoundary caught an error:', error, errorInfo); + console.log({ error, errorInfo }); } + /** 에러 상태 기본 초기화 */ resetErrorBoundary(): void { this.props.onReset(); + this.setState({ hasError: false, error: null, @@ -45,8 +50,11 @@ class ErrorBoundary extends Component { } render() { - const { hasError, error } = this.state; - const { FallbackComponent, children } = this.props; + const { state, props } = this; + + const { hasError, error } = state; + + const { FallbackComponent, children } = props; if (hasError && error) { return ( diff --git a/src/features/profile/container/ClubContents.tsx b/src/features/profile/container/ClubContents.tsx index 689bd1ef..e8e53811 100644 --- a/src/features/profile/container/ClubContents.tsx +++ b/src/features/profile/container/ClubContents.tsx @@ -13,6 +13,9 @@ import { MyWrittenReviewList, WrittenReviewList, } from '../container/index'; +import ErrorHandlingWrapper from '@/app/ErrorHandlingWrapper'; +import ErrorFallback from '@/app/ErrorFallback'; +import Loading from '@/components/loading/Loading'; export default function ClubContents({ isMyPage }: ProfilePageProps) { const [order, setOrder] = useState('DESC'); @@ -62,7 +65,14 @@ export default function ClubContents({ isMyPage }: ProfilePageProps) { /> -
{renderList(selectedList)}
+
+ } + > + {renderList(selectedList)} + +
); } From 036f7e85447b3b756f836a8ca42fc8f854a14de5 Mon Sep 17 00:00:00 2001 From: cloud0406 Date: Wed, 15 Jan 2025 15:20:43 +0900 Subject: [PATCH 04/16] =?UTF-8?q?=E2=99=BB=EF=B8=8F[Refactor]=20=EC=97=90?= =?UTF-8?q?=EB=9F=AC=20=EB=B0=94=EC=9A=B4=EB=8D=94=EB=A6=AC=20=EC=A0=84?= =?UTF-8?q?=ED=8C=8C=EB=A5=BC=20=EC=9C=84=ED=95=B4=20retryOnMount=20?= =?UTF-8?q?=EC=98=B5=EC=85=98=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/lib/utils/reactQueryProvider.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/utils/reactQueryProvider.tsx b/src/lib/utils/reactQueryProvider.tsx index c977b961..4fdc8557 100644 --- a/src/lib/utils/reactQueryProvider.tsx +++ b/src/lib/utils/reactQueryProvider.tsx @@ -9,7 +9,7 @@ export const queryClient = new QueryClient({ refetchOnMount: true, // 컴포넌트가 마운트될 때 데이터를 다시 가져올지 여부 retry: 0, // 실패한 쿼리 재시도 횟수 refetchOnReconnect: false, // 네트워크 재연결시 데이터를 다시 가져올지 여부 - retryOnMount: false, // 마운트 시 실패한 쿼리 재시도 여부 + // retryOnMount: false, // 마운트 시 실패한 쿼리 재시도 여부 staleTime: 1000 * 60 * 5, // 데이터가 'fresh'한 상태로 유지되는 시간 (5분) gcTime: 1000 * 60 * 10, // 사용하지 않는 캐시 데이터가 메모리에서 제거되기까지의 시간 (10분) throwOnError: true, From 631f375e9ef25f9ff2fa2e60bb6d8b94f6774bbc Mon Sep 17 00:00:00 2001 From: cloud0406 Date: Wed, 15 Jan 2025 16:07:47 +0900 Subject: [PATCH 05/16] =?UTF-8?q?=E2=9C=A8[Feat]=20error.tsx=20=ED=85=9C?= =?UTF-8?q?=ED=94=8C=EB=A6=BF=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/ErrorTemplate.tsx | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 src/app/ErrorTemplate.tsx diff --git a/src/app/ErrorTemplate.tsx b/src/app/ErrorTemplate.tsx new file mode 100644 index 00000000..e98d803c --- /dev/null +++ b/src/app/ErrorTemplate.tsx @@ -0,0 +1,39 @@ +'use client'; + +import Button from '@/components/button/Button'; + +interface ErrorTemplateProps { + error: Error; + reset: () => void; + title?: string; + message?: string; + children?: React.ReactNode; +} + +export default function ErrorTemplate({ + error, + reset, + title = '오류가 발생했습니다', + message, + children, +}: ErrorTemplateProps) { + return ( +
+

{title}

+

{message || error.message}

+ + + + {children} +
+ ); +} From 08f057de71b7b526234f2985400e6c5f9070b9c7 Mon Sep 17 00:00:00 2001 From: cloud0406 Date: Wed, 15 Jan 2025 16:08:12 +0900 Subject: [PATCH 06/16] =?UTF-8?q?=E2=9C=A8[Feat]=20=EB=B6=81=ED=81=B4?= =?UTF-8?q?=EB=9F=BD=20=EC=83=9D=EC=84=B1=20=ED=8E=98=EC=9D=B4=EC=A7=80=20?= =?UTF-8?q?Error.tsx=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/bookclub/create/error.tsx | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 src/app/bookclub/create/error.tsx diff --git a/src/app/bookclub/create/error.tsx b/src/app/bookclub/create/error.tsx new file mode 100644 index 00000000..04d565ff --- /dev/null +++ b/src/app/bookclub/create/error.tsx @@ -0,0 +1,20 @@ +'use client'; + +import ErrorTemplate from '@/app/ErrorTemplate'; + +export default function BookClubCreateError({ + error, + reset, +}: { + error: Error & { digest?: string }; + reset: () => void; +}) { + return ( + + ); +} From 3e0cf5f96a5017c56273eb8f247d9b33fec5f3d3 Mon Sep 17 00:00:00 2001 From: cloud0406 Date: Wed, 15 Jan 2025 16:16:36 +0900 Subject: [PATCH 07/16] =?UTF-8?q?=E2=9C=A8[Feat]=20not=20found=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/not-found.tsx | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 src/app/not-found.tsx diff --git a/src/app/not-found.tsx b/src/app/not-found.tsx new file mode 100644 index 00000000..c240c342 --- /dev/null +++ b/src/app/not-found.tsx @@ -0,0 +1,21 @@ +import Button from '@/components/button/Button'; +import Link from 'next/link'; + +export default function NotFound() { + return ( +
+

페이지를 찾을 수 없습니다

+

요청하신 페이지가 존재하지 않습니다

+ + +
+ ); +} From cdc3a48c6d28d61cbc86eb4f3f693d97155cea26 Mon Sep 17 00:00:00 2001 From: cloud0406 Date: Wed, 15 Jan 2025 17:19:04 +0900 Subject: [PATCH 08/16] =?UTF-8?q?=E2=9C=A8[Feat]=20=EA=B8=80=EB=A1=9C?= =?UTF-8?q?=EB=B2=8C=20=EC=97=90=EB=9F=AC=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/global-error.tsx | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 src/app/global-error.tsx diff --git a/src/app/global-error.tsx b/src/app/global-error.tsx new file mode 100644 index 00000000..583f2a64 --- /dev/null +++ b/src/app/global-error.tsx @@ -0,0 +1,34 @@ +'use client'; + +import Button from '@/components/button/Button'; + +export default function GlobalError({ + error, + reset, +}: { + error: Error & { digest?: string }; + reset: () => void; +}) { + return ( + + + +
+

치명적인 오류가 발생했습니다

+

+ {error.message || '서비스에 문제가 발생했습니다'} +

+ +
+ + + ); +} From 59138416a53fe89a5955e1281459412b202a1d69 Mon Sep 17 00:00:00 2001 From: cloud0406 Date: Wed, 15 Jan 2025 17:20:58 +0900 Subject: [PATCH 09/16] =?UTF-8?q?=E2=9C=A8[Feat]=20=EC=A0=84=EC=97=AD=20?= =?UTF-8?q?=ED=86=A0=EC=8A=A4=ED=8A=B8=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/lib/utils/reactQueryProvider.tsx | 29 +++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/src/lib/utils/reactQueryProvider.tsx b/src/lib/utils/reactQueryProvider.tsx index 4fdc8557..568fd6af 100644 --- a/src/lib/utils/reactQueryProvider.tsx +++ b/src/lib/utils/reactQueryProvider.tsx @@ -1,8 +1,35 @@ 'use client'; -import { QueryClientProvider, QueryClient } from '@tanstack/react-query'; +import { + QueryClientProvider, + QueryClient, + QueryCache, + // MutationCache, +} from '@tanstack/react-query'; import { ReactQueryDevtools } from '@tanstack/react-query-devtools'; +import { showToast } from '@/components/toast/toast'; +import { AxiosError } from 'axios'; export const queryClient = new QueryClient({ + queryCache: new QueryCache({ + onError: (error) => { + if (error instanceof AxiosError) { + showToast({ + message: '데이터를 조회하는 중 에러가 발생했습니다.', + type: 'error', + }); + } + }, + }), + // mutationCache: new MutationCache({ + // onError: (error) => { + // if (error instanceof AxiosError) { + // showToast({ + // message: '요청을 처리하는 중 오류가 발생했습니다', + // type: 'error', + // }); + // } + // }, + // }), defaultOptions: { queries: { refetchOnWindowFocus: false, // 윈도우가 다시 포커스될 때 데이터를 다시 가져올지 여부 From e9d73705dd2e61aae77975d476784fbcabc25ab6 Mon Sep 17 00:00:00 2001 From: cloud0406 Date: Wed, 15 Jan 2025 17:55:22 +0900 Subject: [PATCH 10/16] =?UTF-8?q?=20=E2=9C=A8[Feat]=20global=20callback=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/lib/utils/reactQueryProvider.tsx | 31 ++++++++++++++-------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/src/lib/utils/reactQueryProvider.tsx b/src/lib/utils/reactQueryProvider.tsx index 568fd6af..97aefc35 100644 --- a/src/lib/utils/reactQueryProvider.tsx +++ b/src/lib/utils/reactQueryProvider.tsx @@ -3,33 +3,32 @@ import { QueryClientProvider, QueryClient, QueryCache, - // MutationCache, + MutationCache, } from '@tanstack/react-query'; import { ReactQueryDevtools } from '@tanstack/react-query-devtools'; import { showToast } from '@/components/toast/toast'; -import { AxiosError } from 'axios'; export const queryClient = new QueryClient({ queryCache: new QueryCache({ - onError: (error) => { - if (error instanceof AxiosError) { + onError: (error: Error) => { + console.error('Query Error:', error); + showToast({ + message: '데이터를 조회하는 중 에러가 발생했습니다', + type: 'error', + }); + }, + }), + mutationCache: new MutationCache({ + onError: (error: Error, _, __, mutation) => { + if (!mutation.options.onError) { + console.error('Mutation Error:', error); showToast({ - message: '데이터를 조회하는 중 에러가 발생했습니다.', + message: '요청 처리 중 오류가 발생했습니다', type: 'error', }); } }, }), - // mutationCache: new MutationCache({ - // onError: (error) => { - // if (error instanceof AxiosError) { - // showToast({ - // message: '요청을 처리하는 중 오류가 발생했습니다', - // type: 'error', - // }); - // } - // }, - // }), defaultOptions: { queries: { refetchOnWindowFocus: false, // 윈도우가 다시 포커스될 때 데이터를 다시 가져올지 여부 @@ -42,7 +41,7 @@ export const queryClient = new QueryClient({ throwOnError: true, }, mutations: { - throwOnError: true, + throwOnError: false, // TODO: mutation 에러 에러 바운더리로 던져줄지 고민 }, }, }); From b500744f8bf54f1b153a19f0797fc25eecd0889c Mon Sep 17 00:00:00 2001 From: cloud0406 Date: Mon, 20 Jan 2025 14:22:52 +0900 Subject: [PATCH 11/16] =?UTF-8?q?=F0=9F=9A=9A[Rename]=20=EC=97=90=EB=9F=AC?= =?UTF-8?q?=20=ED=8C=8C=EC=9D=BC=EB=93=A4=20=EC=BB=B4=ED=8F=AC=EB=84=8C?= =?UTF-8?q?=ED=8A=B8=EB=A1=9C=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/bookclub/create/error.tsx | 2 +- src/{app => components/error}/ErrorBoundary.tsx | 0 src/{app => components/error}/ErrorFallback.tsx | 0 src/{app => components/error}/ErrorHandlingWrapper.tsx | 0 src/{app => components/error}/ErrorTemplate.tsx | 0 src/features/profile/container/ClubContents.tsx | 4 ++-- 6 files changed, 3 insertions(+), 3 deletions(-) rename src/{app => components/error}/ErrorBoundary.tsx (100%) rename src/{app => components/error}/ErrorFallback.tsx (100%) rename src/{app => components/error}/ErrorHandlingWrapper.tsx (100%) rename src/{app => components/error}/ErrorTemplate.tsx (100%) diff --git a/src/app/bookclub/create/error.tsx b/src/app/bookclub/create/error.tsx index 04d565ff..b6e198e8 100644 --- a/src/app/bookclub/create/error.tsx +++ b/src/app/bookclub/create/error.tsx @@ -1,6 +1,6 @@ 'use client'; -import ErrorTemplate from '@/app/ErrorTemplate'; +import ErrorTemplate from '@/components/error/ErrorTemplate'; export default function BookClubCreateError({ error, diff --git a/src/app/ErrorBoundary.tsx b/src/components/error/ErrorBoundary.tsx similarity index 100% rename from src/app/ErrorBoundary.tsx rename to src/components/error/ErrorBoundary.tsx diff --git a/src/app/ErrorFallback.tsx b/src/components/error/ErrorFallback.tsx similarity index 100% rename from src/app/ErrorFallback.tsx rename to src/components/error/ErrorFallback.tsx diff --git a/src/app/ErrorHandlingWrapper.tsx b/src/components/error/ErrorHandlingWrapper.tsx similarity index 100% rename from src/app/ErrorHandlingWrapper.tsx rename to src/components/error/ErrorHandlingWrapper.tsx diff --git a/src/app/ErrorTemplate.tsx b/src/components/error/ErrorTemplate.tsx similarity index 100% rename from src/app/ErrorTemplate.tsx rename to src/components/error/ErrorTemplate.tsx diff --git a/src/features/profile/container/ClubContents.tsx b/src/features/profile/container/ClubContents.tsx index e8e53811..20b2fadb 100644 --- a/src/features/profile/container/ClubContents.tsx +++ b/src/features/profile/container/ClubContents.tsx @@ -13,8 +13,8 @@ import { MyWrittenReviewList, WrittenReviewList, } from '../container/index'; -import ErrorHandlingWrapper from '@/app/ErrorHandlingWrapper'; -import ErrorFallback from '@/app/ErrorFallback'; +import ErrorHandlingWrapper from '@/components/error/ErrorHandlingWrapper'; +import ErrorFallback from '@/components/error/ErrorFallback'; import Loading from '@/components/loading/Loading'; export default function ClubContents({ isMyPage }: ProfilePageProps) { From 1b161d0e054d3f3258605c2f6f7eb2319a82d079 Mon Sep 17 00:00:00 2001 From: cloud0406 Date: Mon, 20 Jan 2025 15:00:42 +0900 Subject: [PATCH 12/16] =?UTF-8?q?=E2=9C=A8[Feat]=20alertIcon=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/icons/AlertCircleIcon.tsx | 47 ++++++++++++++++++++++++++++++++ public/icons/index.ts | 1 + 2 files changed, 48 insertions(+) create mode 100644 public/icons/AlertCircleIcon.tsx diff --git a/public/icons/AlertCircleIcon.tsx b/public/icons/AlertCircleIcon.tsx new file mode 100644 index 00000000..827efad0 --- /dev/null +++ b/public/icons/AlertCircleIcon.tsx @@ -0,0 +1,47 @@ +import { SVGProps } from 'react'; + +interface AlertCircleIconProps extends SVGProps { + width?: number; + height?: number; +} + +function AlertCircleIcon({ + width = 50, + height = 50, + ...props +}: AlertCircleIconProps) { + return ( + + + + + + ); +} + +export default AlertCircleIcon; diff --git a/public/icons/index.ts b/public/icons/index.ts index 1a23bc21..82d49b5e 100644 --- a/public/icons/index.ts +++ b/public/icons/index.ts @@ -19,3 +19,4 @@ export { default as OnlineIcon } from './OnlineIcon'; export { default as MessageIcon } from './MessageIcon'; export { default as PencilIcon } from './PencilIcon'; export { default as IcCheckOnly } from './IcCheckOnly'; +export { default as AlertCircleIcon } from './AlertCircleIcon'; From 865c22b3b23efa6b93fd3ed9ae160068d12d4286 Mon Sep 17 00:00:00 2001 From: cloud0406 Date: Mon, 20 Jan 2025 15:01:11 +0900 Subject: [PATCH 13/16] =?UTF-8?q?=F0=9F=92=84[Design]=20=EC=97=90=EB=9F=AC?= =?UTF-8?q?=20=ED=8F=B4=EB=B0=B1=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20?= =?UTF-8?q?=EB=94=94=EC=9E=90=EC=9D=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/error/ErrorFallback.tsx | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/components/error/ErrorFallback.tsx b/src/components/error/ErrorFallback.tsx index 6bb3506b..77791d9d 100644 --- a/src/components/error/ErrorFallback.tsx +++ b/src/components/error/ErrorFallback.tsx @@ -1,24 +1,32 @@ 'use client'; +import Button from '@/components/button/Button'; import { FallbackProps } from './ErrorBoundary'; +import { AlertCircleIcon } from '../../../public/icons'; export default function ErrorFallback({ error, resetErrorBoundary, }: FallbackProps) { return ( -
-

오류가 발생했습니다

-

{error?.message}

- +
); } From 3457f01c9ccac52c683684a97a0d7c855cb52f30 Mon Sep 17 00:00:00 2001 From: cloud0406 Date: Mon, 20 Jan 2025 15:09:34 +0900 Subject: [PATCH 14/16] =?UTF-8?q?=F0=9F=92=84[Design]=20=EC=84=9C=EB=B2=84?= =?UTF-8?q?=EC=82=AC=EC=9D=B4=EB=93=9C=20=EC=97=90=EB=9F=AC=20=ED=85=9C?= =?UTF-8?q?=ED=94=8C=EB=A6=BF=20=EB=94=94=EC=9E=90=EC=9D=B8=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/images/errorImage.png | Bin 0 -> 10667 bytes src/components/error/ErrorTemplate.tsx | 7 +++++++ 2 files changed, 7 insertions(+) create mode 100644 public/images/errorImage.png diff --git a/public/images/errorImage.png b/public/images/errorImage.png new file mode 100644 index 0000000000000000000000000000000000000000..328b589698b9c0031b777b4cbe473a84c7ba6d77 GIT binary patch literal 10667 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 + 에러 이미지

{title}

{message || error.message}

From 070457d96f9a98bf214221f91d8e166161909e3b Mon Sep 17 00:00:00 2001 From: cloud0406 Date: Mon, 20 Jan 2025 15:15:02 +0900 Subject: [PATCH 15/16] =?UTF-8?q?=F0=9F=92=84[Design]=20notfound,=20global?= =?UTF-8?q?=20=EC=97=90=EB=9F=AC=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=EC=9D=B4?= =?UTF-8?q?=EB=AF=B8=EC=A7=80=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/global-error.tsx | 8 ++++++++ src/app/not-found.tsx | 15 +++++++++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/app/global-error.tsx b/src/app/global-error.tsx index 583f2a64..14da1ffe 100644 --- a/src/app/global-error.tsx +++ b/src/app/global-error.tsx @@ -1,6 +1,7 @@ 'use client'; import Button from '@/components/button/Button'; +import Image from 'next/image'; export default function GlobalError({ error, @@ -14,6 +15,13 @@ export default function GlobalError({
+ 에러 이미지

치명적인 오류가 발생했습니다

{error.message || '서비스에 문제가 발생했습니다'} diff --git a/src/app/not-found.tsx b/src/app/not-found.tsx index c240c342..4528a6bf 100644 --- a/src/app/not-found.tsx +++ b/src/app/not-found.tsx @@ -1,11 +1,22 @@ import Button from '@/components/button/Button'; import Link from 'next/link'; +import Image from 'next/image'; export default function NotFound() { return (

-

페이지를 찾을 수 없습니다

-

요청하신 페이지가 존재하지 않습니다

+ 에러 이미지 + +
+

페이지를 찾을 수 없습니다

+

요청하신 페이지가 존재하지 않습니다

+