From 09ede03335ebeb1e7d4c9637a637118d55c90d86 Mon Sep 17 00:00:00 2001 From: neungdong Date: Sun, 3 Aug 2025 16:54:04 +0900 Subject: [PATCH 1/7] =?UTF-8?q?refactor(HIGH-47):=20500=EB=B2=88=EB=8C=80?= =?UTF-8?q?=20=EC=97=90=EB=9F=AC=EC=9D=BC=20=EA=B2=BD=EC=9A=B0=20=EC=9E=AC?= =?UTF-8?q?=EC=8B=9C=EB=8F=84=ED=95=98=EB=8F=84=EB=A1=9D=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 --- src/components/common/ErrorFallback.tsx | 50 ++++++++++++++++--------- 1 file changed, 32 insertions(+), 18 deletions(-) diff --git a/src/components/common/ErrorFallback.tsx b/src/components/common/ErrorFallback.tsx index e56b233..2b9b4d4 100644 --- a/src/components/common/ErrorFallback.tsx +++ b/src/components/common/ErrorFallback.tsx @@ -2,43 +2,57 @@ import { useNavigate } from "react-router-dom"; import { HTTPError } from "@/apis/HTTPError"; import { Button } from "@/components/ui/button"; import { HTTP_ERROR_MESSAGES } from "@/constants/api"; -import { PATH } from "@/constants/path"; interface ErrorFallbackProps { error: Error; resetErrorBoundary: () => void; } +const shouldRetry = (err: Error): boolean => { + if (err instanceof HTTPError) { + const retryableStatuses = [500, 502, 503]; + return retryableStatuses.includes(err.status); + } + return false; +}; -const ErrorFallback = ({ error, resetErrorBoundary }: ErrorFallbackProps) => { - const navigate = useNavigate(); +const getMessage = (err: Error): string => { + if (err instanceof HTTPError) { + const message = + HTTP_ERROR_MESSAGES[err.status as keyof typeof HTTP_ERROR_MESSAGES]; - const getMessage = (err: Error): string => { - if (err instanceof HTTPError) { - const message = - HTTP_ERROR_MESSAGES[err.status as keyof typeof HTTP_ERROR_MESSAGES]; + if (typeof message === "function") { + return message(err.status); + } - if (typeof message === "function") { - return message(err.status); - } + return message ?? HTTP_ERROR_MESSAGES.DEFAULT(err.status); + } - return message ?? HTTP_ERROR_MESSAGES.DEFAULT(err.status); - } + return err.message || HTTP_ERROR_MESSAGES.UNKNOWN; +}; - return err.message || HTTP_ERROR_MESSAGES.UNKNOWN; - }; +const ErrorFallback = ({ error, resetErrorBoundary }: ErrorFallbackProps) => { + const navigate = useNavigate(); + const retryable = shouldRetry(error); return (

문제가 발생했어요

-

{getMessage(error)}

+

+ {getMessage(error)} +

+
- + {retryable && ( + + )}
From 9b7a7278c06e62aba9b1ab71f8a3bd7a941d3a12 Mon Sep 17 00:00:00 2001 From: neungdong Date: Sun, 3 Aug 2025 16:55:21 +0900 Subject: [PATCH 2/7] =?UTF-8?q?feat(HIGH-47):=20notfoundpage=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 --- src/AppRouter.tsx | 11 ++++++++--- src/constants/api.ts | 2 +- src/pages/NotFoundPage.tsx | 24 ++++++++++++++++++++++++ 3 files changed, 33 insertions(+), 4 deletions(-) create mode 100644 src/pages/NotFoundPage.tsx diff --git a/src/AppRouter.tsx b/src/AppRouter.tsx index ad5359c..e615d01 100644 --- a/src/AppRouter.tsx +++ b/src/AppRouter.tsx @@ -1,15 +1,16 @@ import { RouterProvider, createBrowserRouter } from "react-router-dom"; import App from "@/App"; import { PATH } from "@/constants/path"; +import AdminPage from "@/pages/AdminPage"; import ContentDetailPage from "@/pages/ContentDetailPage"; import HomePage from "@/pages/HomePage"; import LandingPage from "@/pages/LandingPage"; import MyPage from "@/pages/MyPage"; +import NotFoundPage from "@/pages/NotFoundPage"; import OnBoardingPage from "@/pages/OnBoardingPage"; import RedirectPage from "@/pages/RedirectPage"; -import AdminPage from "./pages/AdminPage"; -import SearchPage from "./pages/SearchPage"; -import ShortsPage from "./pages/ShortsPage"; +import SearchPage from "@/pages/SearchPage"; +import ShortsPage from "@/pages/ShortsPage"; const AppRouter = () => { const router = createBrowserRouter([ @@ -46,6 +47,10 @@ const AppRouter = () => { element: , }, { path: PATH.SEARCH, element: }, + { + path: "*", + element: , + }, ], }, { diff --git a/src/constants/api.ts b/src/constants/api.ts index 3bfa40b..c239a96 100644 --- a/src/constants/api.ts +++ b/src/constants/api.ts @@ -46,7 +46,7 @@ export const AUTH_ERROR_CODE = { } as const; export const HTTP_ERROR_MESSAGES = { - 404: "찾으시는 콘텐츠가 존재하지 않아요.\n주소가 정확한지 확인해 주세요.", + 404: "찾으시는 콘텐츠가 존재하지 않아요.", 500: "서버에 문제가 발생했어요.\n조금 뒤에 다시 시도해 주세요.", DEFAULT: (status: number) => `문제가 발생했어요. (에러 코드: ${status})`, UNKNOWN: "알 수 없는 오류가 발생했어요.\n앱을 다시 실행해 보시겠어요?", diff --git a/src/pages/NotFoundPage.tsx b/src/pages/NotFoundPage.tsx new file mode 100644 index 0000000..fc1c6c9 --- /dev/null +++ b/src/pages/NotFoundPage.tsx @@ -0,0 +1,24 @@ +import { useNavigate } from "react-router-dom"; +import { Button } from "@/components/ui/button"; + +const NotFoundPage = () => { + const navigate = useNavigate(); + + return ( +
+

+ 페이지를 찾을 수 없습니다 +

+

+ 요청하신 주소가 존재하지 않거나 변경되었습니다. +

+ +
+ ); +}; + +export default NotFoundPage; From 542527b804cbb3c6bd84c6adc710a64926df751f Mon Sep 17 00:00:00 2001 From: neungdong Date: Sun, 3 Aug 2025 16:56:04 +0900 Subject: [PATCH 3/7] =?UTF-8?q?feat(HIGH-47):=20=EC=87=BC=EC=B8=A0=20?= =?UTF-8?q?=EB=B9=84=EB=8F=99=EA=B8=B0=20=EB=A1=9C=EB=94=A9=20=EC=97=90?= =?UTF-8?q?=EB=9F=AC=20=ED=86=B5=ED=95=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../queries/shorts/useShortsInfiniteQuery.ts | 10 ++-- src/hooks/shorts/useShortsToShow.ts | 48 ++++--------------- src/pages/ShortsPage.tsx | 32 +++++++++---- 3 files changed, 35 insertions(+), 55 deletions(-) diff --git a/src/hooks/queries/shorts/useShortsInfiniteQuery.ts b/src/hooks/queries/shorts/useShortsInfiniteQuery.ts index 1cb8eb8..ddf4154 100644 --- a/src/hooks/queries/shorts/useShortsInfiniteQuery.ts +++ b/src/hooks/queries/shorts/useShortsInfiniteQuery.ts @@ -1,10 +1,10 @@ -import { useInfiniteQuery } from "@tanstack/react-query"; +import { useSuspenseInfiniteQuery } from "@tanstack/react-query"; import { getShorts } from "@/apis/shorts/getShorts"; import type { GetShortsResponse } from "@/types/shorts"; -export const useShortsInfiniteQuery = (options?: { enabled?: boolean }) => { - const { data, fetchNextPage, hasNextPage, isFetchingNextPage, isLoading } = - useInfiniteQuery({ +export const useShortsInfiniteQuery = () => { + const { data, fetchNextPage, hasNextPage, isFetchingNextPage } = + useSuspenseInfiniteQuery({ queryKey: ["shorts"], queryFn: ({ pageParam = null }) => getShorts({ cursor: pageParam as number | undefined }), @@ -12,7 +12,6 @@ export const useShortsInfiniteQuery = (options?: { enabled?: boolean }) => { lastPage.hasNext ? lastPage.nextCursor : undefined, initialPageParam: null, staleTime: 60 * 1000, - enabled: options?.enabled ?? true, }); const shorts = data?.pages.flatMap((page) => page.items) ?? []; @@ -22,6 +21,5 @@ export const useShortsInfiniteQuery = (options?: { enabled?: boolean }) => { fetchNextPage, hasNextPage, isFetchingNextPage, - isLoading, }; }; diff --git a/src/hooks/shorts/useShortsToShow.ts b/src/hooks/shorts/useShortsToShow.ts index 0f84f19..c4c10ac 100644 --- a/src/hooks/shorts/useShortsToShow.ts +++ b/src/hooks/shorts/useShortsToShow.ts @@ -3,10 +3,8 @@ import { useShortsByIdQuery } from "@/hooks/queries/shorts/useShortsByIdQuery"; import { useShortsInfiniteQuery } from "@/hooks/queries/shorts/useShortsInfiniteQuery"; export function useShortsToShow(currentShortsId?: string) { - const { shorts, fetchNextPage, hasNextPage, isLoading } = - useShortsInfiniteQuery(); + const { shorts, fetchNextPage, hasNextPage } = useShortsInfiniteQuery(); - // 타입 안전한 ID 비교 함수 const isSameShortsId = (shortsId: number, targetId: string) => { return String(shortsId) === targetId && targetId !== ""; }; @@ -18,49 +16,19 @@ export function useShortsToShow(currentShortsId?: string) { [shorts, currentShortsId] ); - const { shorts: singleShorts, isLoading: isSingleShortsLoading } = - useShortsByIdQuery(currentShortsId ?? "", { - enabled: !!currentShortsId && !alreadyHasShort, - }); + const { shorts: singleShorts } = useShortsByIdQuery(currentShortsId ?? "", { + enabled: !!currentShortsId && !alreadyHasShort, + }); const shortsToShow = useMemo(() => { - // currentShortsId가 없으면 기존 목록 반환 - if (!currentShortsId) { - return shorts.filter(Boolean); - } - - // 이미 목록에 있으면 기존 목록 반환 - if (alreadyHasShort) { - return shorts.filter(Boolean); - } - - // 단일 쇼츠가 아직 로딩 중이면 빈 배열 반환 (로딩 완료까지 기다림) - if (isSingleShortsLoading) { - return []; - } - - // 단일 쇼츠를 성공적으로 가져왔으면 맨 앞에 추가 - if (singleShorts) { - return [ - singleShorts, - ...shorts.filter((s) => !isSameShortsId(s.shortsId, currentShortsId)), - ]; - } - - // 단일 쇼츠 로딩 실패 시 기존 목록 반환 - return shorts.filter(Boolean); - }, [ - currentShortsId, - alreadyHasShort, - isSingleShortsLoading, - singleShorts, - shorts, - ]); + if (!currentShortsId || alreadyHasShort) return shorts; + if (!singleShorts) return shorts; + return [singleShorts, ...shorts]; + }, [currentShortsId, alreadyHasShort, shorts, singleShorts]); return { shortsToShow, fetchNextPage, hasNextPage, - isLoading: isLoading || isSingleShortsLoading, }; } diff --git a/src/pages/ShortsPage.tsx b/src/pages/ShortsPage.tsx index 24becb1..c11652c 100644 --- a/src/pages/ShortsPage.tsx +++ b/src/pages/ShortsPage.tsx @@ -1,6 +1,8 @@ +/* eslint-disable no-use-before-define */ import { useRef, useEffect } from "react"; import { useParams } from "react-router-dom"; import { useQueryClient } from "@tanstack/react-query"; +import AsyncBoundary from "@/components/common/AsyncBoundary"; import ShortsLayout from "@/components/shorts/ShortsLayout"; import { useActiveShortsId } from "@/hooks/shorts/useActiveShortsId"; import { useShortsToShow } from "@/hooks/shorts/useShortsToShow"; @@ -9,36 +11,48 @@ import { useShortsWatchTimeTracker } from "@/hooks/shorts/useShortsWatchTimeTrac const ShortsPage = () => { const { id: currentShortsId } = useParams<{ id: string }>(); const queryClient = useQueryClient(); - const { shortsToShow, fetchNextPage, hasNextPage, isLoading } = - useShortsToShow(currentShortsId); - const cardRefs = useRef<(HTMLDivElement | null)[]>([]); - // 쇼츠 페이지를 벗어날 때 무한스크롤 캐시 리셋 useEffect(() => { return () => { - // cleanup 함수: 컴포넌트가 언마운트될 때 실행 queryClient.resetQueries({ queryKey: ["shorts"] }); }; }, [queryClient]); + useShortsWatchTimeTracker({ activeShortsId: currentShortsId }); + + return ( + + + + ); +}; + +function ShortsContent({ + cardRefs, + currentShortsId, +}: { + cardRefs: React.MutableRefObject<(HTMLDivElement | null)[]>; + currentShortsId?: string; +}) { + const { shortsToShow, fetchNextPage, hasNextPage } = + useShortsToShow(currentShortsId); + useActiveShortsId({ shortsToShow, cardRefs, currentShortsId, }); - useShortsWatchTimeTracker({ activeShortsId: currentShortsId }); - return ( ); -}; +} export default ShortsPage; From 2a8d390ec5c06577c0dbc4dab0e46c98f1ab6182 Mon Sep 17 00:00:00 2001 From: neungdong Date: Sun, 3 Aug 2025 17:13:19 +0900 Subject: [PATCH 4/7] =?UTF-8?q?refactor(HIGH-47):=20=EB=A1=9C=EB=94=A9=20?= =?UTF-8?q?=EC=9C=84=EC=9E=84=20=EC=B2=98=EB=A6=AC=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/shorts/useShortsToShow.ts | 43 ++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 7 deletions(-) diff --git a/src/hooks/shorts/useShortsToShow.ts b/src/hooks/shorts/useShortsToShow.ts index c4c10ac..443257f 100644 --- a/src/hooks/shorts/useShortsToShow.ts +++ b/src/hooks/shorts/useShortsToShow.ts @@ -16,15 +16,44 @@ export function useShortsToShow(currentShortsId?: string) { [shorts, currentShortsId] ); - const { shorts: singleShorts } = useShortsByIdQuery(currentShortsId ?? "", { - enabled: !!currentShortsId && !alreadyHasShort, - }); + const { shorts: singleShorts, isLoading: isSingleShortsLoading } = + useShortsByIdQuery(currentShortsId ?? "", { + enabled: !!currentShortsId && !alreadyHasShort, + }); const shortsToShow = useMemo(() => { - if (!currentShortsId || alreadyHasShort) return shorts; - if (!singleShorts) return shorts; - return [singleShorts, ...shorts]; - }, [currentShortsId, alreadyHasShort, shorts, singleShorts]); + // ID 없으면 기존 리스트 반환 + if (!currentShortsId) { + return shorts.filter(Boolean); + } + + // 이미 포함되어 있으면 기존 리스트 반환 + if (alreadyHasShort) { + return shorts.filter(Boolean); + } + + // 단일 쇼츠 로딩 중이면 Suspense fallback이 표시될 것이므로, 일단 비워둠 + if (isSingleShortsLoading) { + return []; + } + + // 단일 쇼츠 성공 시, 가장 앞에 추가 + if (singleShorts) { + return [ + singleShorts, + ...shorts.filter((s) => !isSameShortsId(s.shortsId, currentShortsId)), + ]; + } + + // 실패 fallback: 기존 리스트 + return shorts.filter(Boolean); + }, [ + currentShortsId, + alreadyHasShort, + isSingleShortsLoading, + singleShorts, + shorts, + ]); return { shortsToShow, From 262055a1cba0eea3717df60065c5445d5754b08d Mon Sep 17 00:00:00 2001 From: neungdong Date: Mon, 4 Aug 2025 10:22:05 +0900 Subject: [PATCH 5/7] =?UTF-8?q?refactor(HIGH-47):=20=EB=A7=88=EC=9D=B4?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80=20=EB=A1=9C=EB=94=A9=20=EC=97=90?= =?UTF-8?q?=EB=9F=AC=20=ED=86=B5=ED=95=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/queries/user/useUserInformationQuery.ts | 4 ++-- src/pages/MyPage.tsx | 13 ++++++++++--- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/hooks/queries/user/useUserInformationQuery.ts b/src/hooks/queries/user/useUserInformationQuery.ts index e28586a..dcaa2f8 100644 --- a/src/hooks/queries/user/useUserInformationQuery.ts +++ b/src/hooks/queries/user/useUserInformationQuery.ts @@ -1,9 +1,9 @@ -import { useQuery } from "@tanstack/react-query"; +import { useSuspenseQuery } from "@tanstack/react-query"; import getUserInformation from "@/apis/user/getUserInformation"; import type { UserInformation } from "@/types/user"; const useUserInformationQuery = () => { - const { data: userInformation } = useQuery({ + const { data: userInformation } = useSuspenseQuery({ queryKey: ["userInformation"], queryFn: () => getUserInformation(), staleTime: 60 * 60 * 1000, diff --git a/src/pages/MyPage.tsx b/src/pages/MyPage.tsx index 9d9439d..faad0e0 100644 --- a/src/pages/MyPage.tsx +++ b/src/pages/MyPage.tsx @@ -1,12 +1,19 @@ +import AsyncBoundary from "@/components/common/AsyncBoundary"; import MyLayout from "@/components/My/MyLayout"; import useUserInformationQuery from "@/hooks/queries/user/useUserInformationQuery"; -const MyPage = () => { +const MyPageContent = () => { const { userInformation } = useUserInformationQuery(); - if (!userInformation) return null; - return ; }; +const MyPage = () => { + return ( + + + + ); +}; + export default MyPage; From bbb039e6ee357d2b046d07552291878d8af1cd0d Mon Sep 17 00:00:00 2001 From: neungdong Date: Mon, 4 Aug 2025 10:22:54 +0900 Subject: [PATCH 6/7] =?UTF-8?q?chore(HIGH-47):=20=ED=8F=AC=EC=9D=B8?= =?UTF-8?q?=ED=8A=B8=20=EC=83=89=EC=83=81=20=EC=B1=84=EB=8F=84=20=EB=82=AE?= =?UTF-8?q?=EC=B6=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tailwind.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tailwind.config.js b/tailwind.config.js index 6748332..25ac597 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -60,7 +60,7 @@ export default { }, custom: { black: "#141516", - point: "#40FEA4", + point: "#2FC88F", gray: "#A1A1A1", darkgray: "#4A4949", }, From b9e2b47da65e58041402ad6e0561e499a9e755ce Mon Sep 17 00:00:00 2001 From: neungdong Date: Mon, 4 Aug 2025 10:23:36 +0900 Subject: [PATCH 7/7] =?UTF-8?q?feat(HIGH-47):=20=EB=8B=A4=EC=9D=B4?= =?UTF-8?q?=EB=82=98=EB=AF=B9=20=EC=9E=84=ED=8F=AC=ED=8A=B8=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/AppRouter.tsx | 63 ------------------------ src/main.tsx | 2 +- src/router/AppRouter.tsx | 100 +++++++++++++++++++++++++++++++++++++++ src/router/lazy.ts | 14 ++++++ 4 files changed, 115 insertions(+), 64 deletions(-) delete mode 100644 src/AppRouter.tsx create mode 100644 src/router/AppRouter.tsx create mode 100644 src/router/lazy.ts diff --git a/src/AppRouter.tsx b/src/AppRouter.tsx deleted file mode 100644 index e615d01..0000000 --- a/src/AppRouter.tsx +++ /dev/null @@ -1,63 +0,0 @@ -import { RouterProvider, createBrowserRouter } from "react-router-dom"; -import App from "@/App"; -import { PATH } from "@/constants/path"; -import AdminPage from "@/pages/AdminPage"; -import ContentDetailPage from "@/pages/ContentDetailPage"; -import HomePage from "@/pages/HomePage"; -import LandingPage from "@/pages/LandingPage"; -import MyPage from "@/pages/MyPage"; -import NotFoundPage from "@/pages/NotFoundPage"; -import OnBoardingPage from "@/pages/OnBoardingPage"; -import RedirectPage from "@/pages/RedirectPage"; -import SearchPage from "@/pages/SearchPage"; -import ShortsPage from "@/pages/ShortsPage"; - -const AppRouter = () => { - const router = createBrowserRouter([ - { - path: PATH.ROOT, - element: , - children: [ - { - path: "", - element: , - }, - { - path: PATH.HOME, - element: , - }, - { - path: PATH.CONTENT_DETAIL, - element: , - }, - { - path: PATH.SHORTS, - element: , - }, - { - path: PATH.REDIRECT, - element: , - }, - { - path: PATH.ONBOARDING, - element: , - }, - { - path: PATH.MYPAGE, - element: , - }, - { path: PATH.SEARCH, element: }, - { - path: "*", - element: , - }, - ], - }, - { - path: PATH.ADMIN, - element: , - }, - ]); - return ; -}; -export default AppRouter; diff --git a/src/main.tsx b/src/main.tsx index b0a2d7a..98cc018 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -2,7 +2,7 @@ import { StrictMode } from "react"; import { createRoot } from "react-dom/client"; import { QueryClientProvider } from "@tanstack/react-query"; import { queryClient } from "@/hooks/queries/common/queryClient"; -import AppRouter from "./AppRouter"; +import AppRouter from "./router/AppRouter"; import "./index.css"; createRoot(document.getElementById("root")!).render( diff --git a/src/router/AppRouter.tsx b/src/router/AppRouter.tsx new file mode 100644 index 0000000..7d1d4b3 --- /dev/null +++ b/src/router/AppRouter.tsx @@ -0,0 +1,100 @@ +import { Suspense } from "react"; +import { RouterProvider, createBrowserRouter } from "react-router-dom"; +import App from "@/App"; +import { PATH } from "@/constants/path"; +import * as Lazy from "./lazy"; + +const AppRouter = () => { + const router = createBrowserRouter([ + { + path: PATH.ROOT, + element: , + children: [ + { + path: "", + element: ( + + + + ), + }, + { + path: PATH.HOME, + element: ( + + + + ), + }, + { + path: PATH.CONTENT_DETAIL, + element: ( + + + + ), + }, + { + path: PATH.SHORTS, + element: ( + + + + ), + }, + { + path: PATH.REDIRECT, + element: ( + + + + ), + }, + { + path: PATH.ONBOARDING, + element: ( + + + + ), + }, + { + path: PATH.MYPAGE, + element: ( + + + + ), + }, + { + path: PATH.SEARCH, + element: ( + + + + ), + }, + { + path: "*", + element: ( + + + + ), + }, + ], + }, + { + path: PATH.ADMIN, + element: ( + + + + ), + }, + ]); + + return ; +}; + +export default AppRouter; diff --git a/src/router/lazy.ts b/src/router/lazy.ts new file mode 100644 index 0000000..c1f5862 --- /dev/null +++ b/src/router/lazy.ts @@ -0,0 +1,14 @@ +import { lazy } from "react"; + +export const LandingPage = lazy(() => import("@/pages/LandingPage")); +export const HomePage = lazy(() => import("@/pages/HomePage")); +export const ContentDetailPage = lazy( + () => import("@/pages/ContentDetailPage") +); +export const ShortsPage = lazy(() => import("@/pages/ShortsPage")); +export const RedirectPage = lazy(() => import("@/pages/RedirectPage")); +export const OnBoardingPage = lazy(() => import("@/pages/OnBoardingPage")); +export const MyPage = lazy(() => import("@/pages/MyPage")); +export const SearchPage = lazy(() => import("@/pages/SearchPage")); +export const AdminPage = lazy(() => import("@/pages/AdminPage")); +export const NotFoundPage = lazy(() => import("@/pages/NotFoundPage"));