diff --git a/src/app/auth/callback/page.tsx b/src/app/auth/callback/page.tsx index 5eb3675..0a2f8af 100644 --- a/src/app/auth/callback/page.tsx +++ b/src/app/auth/callback/page.tsx @@ -1,35 +1,51 @@ 'use client'; import { useEffect } from 'react'; -import { useRouter } from 'next/navigation'; +import { useRouter, useSearchParams } from 'next/navigation'; import { supabase } from '@/lib/supabase'; +import { Suspense } from 'react'; -export default function AuthCallback() { +function AuthCallbackInner() { const router = useRouter(); + const searchParams = useSearchParams(); useEffect(() => { + // 카카오 로그인 취소 시 error=access_denied 쿼리가 붙어서 돌아옴 + const errorParam = searchParams.get('error'); + if (errorParam) { + router.replace('/'); + return; + } + const handleAuth = async () => { - // 1. URL에 포함된 토큰을 이용해 세션을 가져옵니다. - // 이 과정에서 Supabase 라이브러리가 브라우저 쿠키/로컬스토리지에 로그인 정보를 저장합니다. const { data, error } = await supabase.auth.getSession(); if (data.session) { - // 2. 로그인이 확인되면 메인 페이지('/')로 이동시킵니다. - // router.replace를 쓰면 주소창이 깔끔하게 '/'로 바뀌고 뒤로가기가 방지됩니다. router.replace('/'); } else if (error) { console.error('로그인 처리 중 오류:', error.message); router.replace('/'); + } else { + // session도 error도 없으면 (ex. 직접 URL 접근) 홈으로 + router.replace('/'); } }; handleAuth(); - }, [router]); + }, [router, searchParams]); return (
-

카카오로그인 중...

+

카카오 로그인 중...

); } + +export default function AuthCallback() { + return ( + + + + ); +} diff --git a/src/app/page.tsx b/src/app/page.tsx index acd9a57..b9536f4 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -13,8 +13,8 @@ export default async function Home() { {/* 헤더 */}
- {/* 지도 */} -
+ {/* 지도 — contain-layout으로 내부 레이아웃이 외부에 영향주지 않도록 격리 */} +
diff --git a/src/app/sitemap.ts b/src/app/sitemap.ts index 3d92a83..3fb8ae4 100644 --- a/src/app/sitemap.ts +++ b/src/app/sitemap.ts @@ -1,28 +1,42 @@ import { MetadataRoute } from 'next'; +import { supabase } from '@/lib/supabase'; export default async function sitemap(): Promise { const baseUrl = 'https://gachamap.vercel.app'; - const routes: MetadataRoute.Sitemap = [ + const staticRoutes: MetadataRoute.Sitemap = [ { url: baseUrl, - lastModified: new Date(), + lastModified: new Date('2025-01-01'), changeFrequency: 'daily', priority: 1, }, { url: `${baseUrl}/gacha-board`, - lastModified: new Date(), + lastModified: new Date('2025-01-01'), changeFrequency: 'daily', priority: 0.9, }, { url: `${baseUrl}/about`, - lastModified: new Date(), + lastModified: new Date('2025-01-01'), changeFrequency: 'monthly', priority: 0.5, }, ]; - return routes; + // 가챠보드 게시글 동적 포함 + const { data: posts } = await supabase + .from('gacha_posts') + .select('id, created_at') + .order('created_at', { ascending: false }); + + const postRoutes: MetadataRoute.Sitemap = (posts ?? []).map((post) => ({ + url: `${baseUrl}/gacha-board/${post.id}`, + lastModified: new Date(post.created_at), + changeFrequency: 'weekly' as const, + priority: 0.7, + })); + + return [...staticRoutes, ...postRoutes]; } diff --git a/src/components/Map.tsx b/src/components/Map.tsx index d302202..1db3695 100644 --- a/src/components/Map.tsx +++ b/src/components/Map.tsx @@ -230,38 +230,36 @@ export default function KakaoMap({ shops }: MapProps) { setIsSuggestionModalOpen(true); }; - if (!isMapLoaded) { - return ( -
-
- - - - -

지도를 불러오는 중...

-
-
- ); - } - return (
+ {/* 지도 로딩 오버레이 — 컨테이너 크기는 항상 유지해 CLS 방지 */} + {!isMapLoaded && ( +
+
+ + + + +

지도를 불러오는 중...

+
+
+ )} {/* 카테고리 필터 */}