diff --git a/apps/web/src/routes/callvan.index.tsx b/apps/web/src/routes/callvan.index.tsx index 88ddc209..76fb4b50 100644 --- a/apps/web/src/routes/callvan.index.tsx +++ b/apps/web/src/routes/callvan.index.tsx @@ -9,7 +9,7 @@ import CallvanList from 'components/Callvan/components/CallvanList'; import CallvanPageLayout from 'components/Callvan/components/CallvanPageLayout'; import { type CallvanParams, parseCallvanQuery } from 'components/Callvan/utils/callvanQuery'; import ROUTES from 'static/routes'; -import useMediaQuery from 'utils/hooks/layout/useMediaQuery'; +import useMediaQuery, { MOBILE_QUERY } from 'utils/hooks/layout/useMediaQuery'; import useIsLoggedIn from 'utils/hooks/state/useIsLoggedIn'; import useMount from 'utils/hooks/state/useMount'; import useInfiniteScroll from 'utils/hooks/ui/useInfiniteScroll'; @@ -57,14 +57,13 @@ function useCallvanParams(initialParams: CallvanParams): CallvanParams { function CallvanPage({ initialParams }: Awaited>) { const routeNavigate = useNavigate(); const isMobile = useMediaQuery(); - const mounted = useMount(); - // 서버가 이미 걸러내지만, 창 크기를 줄여 모바일 폭이 된 뒤 넓히는 경우를 위해 남긴다. + // 콜밴은 모바일 폭에서만 연다. 기기(UA)가 아니라 화면 폭으로 판단해 창을 좁힌 데스크톱도 허용한다. useEffect(() => { - if (mounted && !isMobile) { + if (!isMobile && !window.matchMedia(MOBILE_QUERY).matches) { routeNavigate({ href: ROUTES.Main(), replace: true }); } - }, [mounted, isMobile, routeNavigate]); + }, [isMobile, routeNavigate]); const params = useCallvanParams(initialParams); @@ -114,8 +113,9 @@ function CallvanContent({ params }: CallvanContentProps) { } const loadPage = definePageLoad(async ({ search: query, queryClient }, _cacheControl, serverRequest) => { - if (serverRequest.device !== 'mobile') { - throw redirect({ href: ROUTES.Main(), statusCode: 302 }); + // 화면 이동은 브라우저에서 실행되므로 실제 폭으로 바로 거른다. SSR은 폭을 모르니 화면 컴포넌트가 거른다. + if (typeof window !== 'undefined' && !window.matchMedia(MOBILE_QUERY).matches) { + throw redirect({ href: ROUTES.Main() }); } const params = parseCallvanQuery(query, DEFAULT_PARAMS); diff --git a/apps/web/src/utils/hooks/layout/useMediaQuery.ts b/apps/web/src/utils/hooks/layout/useMediaQuery.ts index 76c9166b..97f6f507 100644 --- a/apps/web/src/utils/hooks/layout/useMediaQuery.ts +++ b/apps/web/src/utils/hooks/layout/useMediaQuery.ts @@ -2,7 +2,7 @@ import { useSyncExternalStore } from 'react'; import { useServerRequest } from 'utils/ssr/useServerRequest'; -const MOBILE_QUERY = '(max-width: 576px)'; +export const MOBILE_QUERY = '(max-width: 576px)'; function subscribeToMediaQuery(query: string) { return (onStoreChange: () => void) => {