본문 바로가기
기타

구글 로그인 구현하기(React, FedCM)

by 검은도자기 2024. 10. 6.

개요

아래 사진처럼 실행 가능한 구글 로그인 기능 구현 위해 삽질했던 내용들을 기록할까 합니다.

구현을 위해 먼저 간단한 로그인 프로세스부터 확인해 보겠습니다.

 

구글 로그인 데모

 

https://developers.google.com/identity/gsi/web/guides/overview?hl=ko#sign_in_with_google_demo

 

개요  |  Authentication  |  Google for Developers

Google ID 서비스가 FedCM API로 마이그레이션됩니다. 이전 가이드에 따라 잠재적인 변경사항을 검토하고 웹사이트에 대한 사용자 로그인에 부정적인 영향을 미치지 않도록 하세요. 이 페이지는 Cloud

developers.google.com

 

로그인 프로세스

구글 인증 흐름 프로세스

구글에서 제공하는 로그인 기능의 프로세스는 위 사진과 같으며 인증 흐름이 암시적 흐름이냐 승인 코드 흐름이냐에 따라 로그인 프로세스가 약간 달라집니다.

간단한 기능 테스트를 위한 리액트 코드를 만들어서 테스트를 진행해 보겠습니다.

 

구글 로그인 JavaScript 코드

const GoogleAuthJavaScriptButton: React.FC = () => {
    const [isGoogleLoaded, setIsGoogleLoaded] = useState(false);

    useEffect(() => {
        const loadGoogleScript = () => {
            const script = document.createElement('script');
            script.src = 'https://accounts.google.com/gsi/client';
            script.async = true;
            script.defer = true;
            script.onload = () => setIsGoogleLoaded(true);
            document.body.appendChild(script);
            return script;
        };

        const script = loadGoogleScript();
        return () => {
            document.body.removeChild(script);
        };
    }, []);

    const handleCredentialResponse = useCallback((response: any) => {
        console.log("인코딩된 JWT ID 토큰: " + response.credential);
    }, []);

    useEffect(() => {
        if (isGoogleLoaded && window.google) {
            window.google.accounts.id.initialize({
                client_id: clientId, // googlecloud 페이지에서 발급 받은 값 사용
                callback: handleCredentialResponse,
            });
            window.google.accounts.id.prompt((notification) => {
                if (notification.isNotDisplayed() || notification.isSkippedMoment()) {
                    // continue with another identity provider.
                }
            });

            window.google.accounts.id.renderButton(
                document.getElementById("googleSignInDiv"),
                { theme: "outline", size: "large", text: "continue_with", shape: "rectangular" }
            );
        }
    }, [isGoogleLoaded, handleCredentialResponse]);

    return (
        <div>
            <div id='googleSignInDiv'></div>
        </div>
    );
};

export default GoogleAuthJavaScriptButton;

 

 

구글 로그인 기능 테스트

코드 실행하여 테스트해 본 결과 기능적으로는 문제가 없었으나 로그창에 FedCM 마이그레이션 경고와 여러 에러 메시지가 나왔습니다. 이게 왜 나왔나? 하고 서칭 해보았습니다.

 

[GSI_LOGGER]: FedCM get() rejects with AbortError: signal is aborted without reason

이 에러는 window.google.accounts.id.prompt 이 코드를 주석 처리하니 안 나왔으며, 주석 처리하고 코드 실행해도 동작에는 문제가 없었습니다.

구글 문서를 찾아보니 FedCM 관련 기능이 있는 코드이고 아직 이 기능이 마이그레이션 진행 중이라 불안정해서 에러가 나는구나 하고 파악이 되었습니다. 

 

client:337 Cross-Origin-Opener-Policy policy would block the window.postMessage call.

이 에러는 Cross-Origin-Opener-Policy (COOP)라는 보안 정책 때문에 발생한 것으로 파악되었습니다. 물론 코드 동작에는 문제는 없어 보입니다.

 

기존 구글 로그인 코드가 문제가 있는 건가?

위 궁금증이 있어서 구글 문서를 좀 더 찾아보니, 다른 버전의 코드가 있기에 참고하여 간단하게 실행 가능한 리액트 코드를 만들어봤습니다.

 

새 버전 방식의 구글 로그인 코드

const GoogleAuthCodeButton: React.FC = () => {
    const [isGoogleLoaded, setIsGoogleLoaded] = useState(false);
    const [googleClient, setGoogleClient] = useState(null);

    useEffect(() => {
        const script = document.createElement('script');
        script.src = 'https://accounts.google.com/gsi/client';
        script.async = true;
        script.defer = true;
        script.onload = () => setIsGoogleLoaded(true);
        document.body.appendChild(script);

        return () => {
            document.body.removeChild(script);
        };
    }, []);

    useEffect(() => {
        if (isGoogleLoaded && window.google) {
            const client = window.google.accounts.oauth2.initCodeClient({
                client_id: clientId, // googlecloud 페이지에서 발급 받은 값 사용
                scope: 'https://www.googleapis.com/auth/userinfo.profile',
                ux_mode: 'popup',
                callback: (response: any) => {
                    console.log('Auth code response: ' + response.code);
                },
            });
            setGoogleClient(client);
        }
    }, [isGoogleLoaded, clientId]);

    const handleLogin = useCallback(() => {
        if (googleClient) {
            googleClient.requestCode();
        } else {
            console.error('Google client is not initialized');
        }
    }, [googleClient]);

    return (
        <button onClick={handleLogin} disabled={!isGoogleLoaded}>
            Login with Google
        </button>
    );
};

export default GoogleAuthCodeButton;

 

새 버전 방식의 구글 로그인 테스트

위 코드를 실행하여 로그인 기능 테스트를 해보니 이전 코드에서 나왔던 에러 및 경고표시가 없어진 걸 확인할 수 있었습니다.

 

새 버전 방식의 구글 로그인 기능은 괜찮은 건가?

이 부분에 대해 궁금하여 서칭 해본 결과 oauth2 코드가 있는 페이지에서는 마이그레이션 경고가 없었으며, 기존 google.accounts로 시작하는 페이지에는 경고창이 있는 걸 확인하였습니다. 

 

결론

여러 버전의 구글 로그인 코드를 테스트해본 결과. 기존 구글 로그인 버전은 언제 장애가 날지 모르니 코드 수정이 필요해 보이며, 새로 구현한다면 “oauth2”로 시작하는 코드를 사용하는 게 좋아 보입니다.

하지만 “oauth2” 이 버전도 당장은 문제가 없어 보이나 언제 내용이 바뀔지 모르니 google 문서 모니터링은 필요해 보입니다.

 

마무리

구글 로그인 기능에 대해 분석한 내용을 정리해 보았습니다.

기능에 대해 분석은 했는데 그냥 넘어가기엔 아까워서 정리를 해보았는데요.

앞으로 그냥 넘어가기에 아까운 분석 정리글은 다듬어서 포스팅할까 합니다.

오랜만에 포스팅해보니 정리글 쓰는 게 조금 버거웠네요.

이번 포스팅은 마무리하면서 다른 주제의 포스팅에서 뵙겠습니다.

 

참고

https://developers.google.com/identity/gsi/web/guides/overview?hl=ko

 

개요  |  Authentication  |  Google for Developers

Google ID 서비스가 FedCM API로 마이그레이션됩니다. 이전 가이드에 따라 잠재적인 변경사항을 검토하고 웹사이트에 대한 사용자 로그인에 부정적인 영향을 미치지 않도록 하세요. 이 페이지는 Cloud

developers.google.com

 

'기타' 카테고리의 다른 글

한빛N MSA - #6 Open Source 세미나 후기  (0) 2023.10.27