From 0222eca381d1a92e3f01808dd00a116adc42280a Mon Sep 17 00:00:00 2001 From: gahusb Date: Thu, 19 Mar 2026 23:44:54 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20Google=20OAuth=20=EB=A1=9C=EA=B7=B8?= =?UTF-8?q?=EC=9D=B8=20=EC=8B=9C=20localhost:3000=20=EB=A6=AC=EB=8B=A4?= =?UTF-8?q?=EC=9D=B4=EB=A0=89=ED=8A=B8=20=EB=AC=B8=EC=A0=9C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - app/auth/callback/route.ts: NEXT_PUBLIC_SITE_URL 우선, x-forwarded-host 폴백 Vercel 내부 라우팅에서 request.url의 origin이 localhost로 잡히는 경우 대응 - app/login/page.tsx: signInWithOAuth redirectTo를 NEXT_PUBLIC_SITE_URL 기준으로 변경 window.location.origin 대신 명시적 환경변수 사용으로 안정성 확보 Vercel 환경변수에 NEXT_PUBLIC_SITE_URL=https://<도메인> 추가 필요 Co-Authored-By: Claude Sonnet 4.6 --- app/auth/callback/route.ts | 22 ++++++++++++---------- app/login/page.tsx | 4 +++- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/app/auth/callback/route.ts b/app/auth/callback/route.ts index 27401f8..718a862 100644 --- a/app/auth/callback/route.ts +++ b/app/auth/callback/route.ts @@ -6,21 +6,23 @@ export async function GET(request: Request) { const code = searchParams.get('code'); const next = searchParams.get('next') ?? '/mypage'; + // 프로덕션 기준 URL 결정 + // 우선순위: NEXT_PUBLIC_SITE_URL > x-forwarded-host > origin + const siteUrl = process.env.NEXT_PUBLIC_SITE_URL; + const forwardedHost = request.headers.get('x-forwarded-host'); + const baseUrl = + siteUrl ?? + (process.env.NODE_ENV !== 'development' && forwardedHost + ? `https://${forwardedHost}` + : origin); + if (code) { const supabase = await createClient(); const { error } = await supabase.auth.exchangeCodeForSession(code); if (!error) { - const forwardedHost = request.headers.get('x-forwarded-host'); - const isLocalEnv = process.env.NODE_ENV === 'development'; - if (isLocalEnv) { - return NextResponse.redirect(`${origin}${next}`); - } else if (forwardedHost) { - return NextResponse.redirect(`https://${forwardedHost}${next}`); - } else { - return NextResponse.redirect(`${origin}${next}`); - } + return NextResponse.redirect(`${baseUrl}${next}`); } } - return NextResponse.redirect(`${origin}/login?error=auth-callback-error`); + return NextResponse.redirect(`${baseUrl}/login?error=auth-callback-error`); } diff --git a/app/login/page.tsx b/app/login/page.tsx index 7f1b9da..477c90c 100644 --- a/app/login/page.tsx +++ b/app/login/page.tsx @@ -60,9 +60,11 @@ function LoginForm() { }; const handleGoogleLogin = async () => { + // NEXT_PUBLIC_SITE_URL 이 설정되어 있으면 우선 사용 (localhost 리다이렉트 방지) + const base = process.env.NEXT_PUBLIC_SITE_URL ?? window.location.origin; const { error } = await supabase.auth.signInWithOAuth({ provider: 'google', - options: { redirectTo: `${window.location.origin}/auth/callback` }, + options: { redirectTo: `${base}/auth/callback` }, }); if (error) setMessage('Google 로그인 오류: ' + error.message); };