"use client"; /** 구글이 그려주는 버튼. 우리가 모양을 흉내 내면 브랜드 규정에 걸린다 */ import { useEffect, useRef, useState } from "react"; import { fetchConfig, loadGoogleIdentity, type GoogleButtonOptions, } from "@/lib/auth"; export default function GoogleSignIn({ onCredential, text = "signin_with" }: { onCredential: (credential: string) => void; text?: GoogleButtonOptions["text"]; }) { const host = useRef(null); const [error, setError] = useState(null); // 콜백이 매 렌더마다 바뀌어도 구글에 다시 등록하지 않게 최신 것만 들고 있는다 const latest = useRef(onCredential); latest.current = onCredential; useEffect(() => { let cancelled = false; (async () => { const config = await fetchConfig(); if (!config.enabled) throw new Error("구글 로그인이 설정되지 않았습니다"); const google = await loadGoogleIdentity(); if (cancelled || !host.current) return; google.initialize({ client_id: config.client_id, callback: (response) => { if (response.credential) latest.current(response.credential); }, auto_select: false, cancel_on_tap_outside: true, }); google.renderButton(host.current, { type: "standard", theme: "filled_black", size: "large", shape: "pill", text, logo_alignment: "center", width: 320, }); })().catch((failure) => { if (!cancelled) setError((failure as Error).message); }); return () => { cancelled = true; }; // eslint-disable-next-line react-hooks/exhaustive-deps }, [text]); if (error) { return

{error}

; } return
; }