Feat: 소셜 로그인 추가 및 인증 페이지 UI 테마 정리
app/login/page.tsx - Google/Kakao 소셜 로그인 버튼을 폼으로 연동하고 액션 호출 추가 - 로그인 페이지의 배경/버튼/텍스트 색상 등 UI 테마를 파스텔에서 그레이/다크톤으로 통일 - 소셜 버튼 마크업 및 스타일 정리 app/signup/page.tsx - 회원가입 페이지 배경 및 버튼 색상을 그레이/다크톤으로 변경 - 아이콘 배경 그라디언트 및 링크 색상 업데이트 app/forgot-password/page.tsx - 비밀번호 재설정 요청 페이지의 배경, 블러 효과 및 버튼 스타일을 그레이/다크톤으로 변경 - 아이콘 배경 및 링크 색상 업데이트 app/reset-password/page.tsx - 비밀번호 재설정 페이지의 배경, 블러 효과 및 버튼 스타일을 그레이/다크톤으로 변경 - 아이콘 배경 업데이트 features/auth/actions.ts - Google 및 Kakao OAuth 시작을 위한 공통 헬퍼(signInWithProvider) 추가 - signInWithGoogle 및 signInWithKakao 액션을 구현하여 OAuth 흐름을 시작하도록 추가
This commit is contained in:
@@ -385,3 +385,94 @@ export async function updatePassword(formData: FormData) {
|
||||
`/login?message=${encodeURIComponent(AUTH_ERROR_MESSAGES.PASSWORD_RESET_SUCCESS)}`,
|
||||
);
|
||||
}
|
||||
|
||||
// ========================================
|
||||
// 소셜 로그인 (OAuth)
|
||||
// ========================================
|
||||
|
||||
/**
|
||||
* [OAuth 로그인 헬퍼 함수]
|
||||
*
|
||||
* Google, Kakao 등의 소셜 로그인 제공자를 통해 인증을 수행합니다.
|
||||
*
|
||||
* PKCE (Proof Key for Code Exchange) 플로우:
|
||||
* 1. 이 함수가 signInWithOAuth를 호출하면 Supabase가 OAuth URL 반환
|
||||
* 2. 사용자를 해당 OAuth 제공자(Google/Kakao) 로그인 페이지로 리다이렉트
|
||||
* 3. 사용자가 로그인 및 권한 동의
|
||||
* 4. OAuth 제공자가 /auth/callback?code=xxx로 리다이렉트
|
||||
* 5. callback 라우트에서 code를 세션으로 교환 (exchangeCodeForSession)
|
||||
* 6. 메인 페이지로 최종 리다이렉트
|
||||
*
|
||||
* 자동 회원가입:
|
||||
* - 첫 로그인 시 auth.users 테이블에 자동으로 사용자 생성
|
||||
* - 이메일, provider, metadata(프로필 사진, 이름 등) 저장
|
||||
* - 기존 사용자는 그냥 로그인
|
||||
*
|
||||
* @param provider - OAuth 제공자 ('google' | 'kakao')
|
||||
*/
|
||||
async function signInWithProvider(provider: "google" | "kakao") {
|
||||
const supabase = await createClient();
|
||||
|
||||
// 1. OAuth 인증 시작
|
||||
const { data, error } = await supabase.auth.signInWithOAuth({
|
||||
provider,
|
||||
options: {
|
||||
// PKCE 플로우를 위한 콜백 URL
|
||||
// OAuth 제공자 인증 후 이 URL로 code와 함께 리다이렉트됨
|
||||
redirectTo: `${process.env.NEXT_PUBLIC_BASE_URL || "http://localhost:3001"}/auth/callback`,
|
||||
},
|
||||
});
|
||||
|
||||
// 2. 에러 처리
|
||||
if (error) {
|
||||
console.error(`[${provider} OAuth] 로그인 실패:`, error.message);
|
||||
return redirect(
|
||||
`/login?message=${encodeURIComponent(`${provider} 로그인에 실패했습니다. 다시 시도해 주세요.`)}`,
|
||||
);
|
||||
}
|
||||
|
||||
// 3. OAuth 제공자 로그인 페이지로 리다이렉트
|
||||
// data.url은 Google/Kakao의 인증 페이지 URL
|
||||
if (data.url) {
|
||||
redirect(data.url);
|
||||
}
|
||||
|
||||
// 4. URL이 없는 경우 (예상치 못한 상황)
|
||||
redirect(
|
||||
`/login?message=${encodeURIComponent("로그인 처리 중 오류가 발생했습니다.")}`,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* [Google 로그인 액션]
|
||||
*
|
||||
* Google 계정으로 로그인합니다.
|
||||
* "Google로 로그인" 버튼에서 호출됩니다.
|
||||
*
|
||||
* 처리 과정:
|
||||
* 1. signInWithOAuth 호출하여 Google OAuth URL 받기
|
||||
* 2. Google 로그인 페이지로 리다이렉트
|
||||
* 3. (사용자가 Google에서 로그인 및 권한 동의)
|
||||
* 4. /auth/callback으로 돌아와서 세션 생성
|
||||
* 5. 메인 페이지로 이동
|
||||
*/
|
||||
export async function signInWithGoogle() {
|
||||
return signInWithProvider("google");
|
||||
}
|
||||
|
||||
/**
|
||||
* [Kakao 로그인 액션]
|
||||
*
|
||||
* Kakao 계정으로 로그인합니다.
|
||||
* "Kakao로 로그인" 버튼에서 호출됩니다.
|
||||
*
|
||||
* 처리 과정:
|
||||
* 1. signInWithOAuth 호출하여 Kakao OAuth URL 받기
|
||||
* 2. Kakao 로그인 페이지로 리다이렉트
|
||||
* 3. (사용자가 Kakao에서 로그인 및 권한 동의)
|
||||
* 4. /auth/callback으로 돌아와서 세션 생성
|
||||
* 5. 메인 페이지로 이동
|
||||
*/
|
||||
export async function signInWithKakao() {
|
||||
return signInWithProvider("kakao");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user