ํ์ฌ์์ Next๋ฅผ ์ฌ์ฉํ๊ณ ์๋ Web์ Google Login ์ง์์ ์ํด ์น์ฉ Google ๊ณ์ ์ผ๋ก ๋ก๊ทธ์ธ ๊ธฐ๋ฅ์ ๊ตฌํํด์ผ ํด์ ๋ง์ ์ฌ๋๋ค์ด ์ฌ์ฉํ๋ react-google-login ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ ค๊ณ ํ์ง๋ง
๋ ์ด์ ๊ตฌ๊ธ์์ ์ง์ํ์ง ์๋ ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ผ์ ์๋ฌ๊ฐ ๋ฐ์ํ๋ค.
๋ค๋ฅธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ ค๋ค๊ฐ ์๋์ ๊ตฌ๊ธ ๊ฐ๋ฐ์ ํ์ด์ง๋ฅผ ์ฐธ๊ณ ํ์ฌ Google Identity Service(GSI)๋ฅผ ์ด์ฉํ์ฌ ๋ก๊ทธ์ธ์ ๊ตฌํํด๋ณด๊ธฐ๋ก ํ๋ค.
๊ณต์ ๋ฌธ์ ๋งํฌ
๊ตฌ๊ธ ๊ฐ๋ฐ์ ํ์ด์ง Authentication - ์น์ฉ Google ๊ณ์ ์ผ๋ก ๋ก๊ทธ์ธ
Google ๋ก๊ทธ์ธ ํน์ง
- Google ๊ณ์ ์ผ๋ก ์น ์๋น์ค์์ ์ฌ์ฉ์ ์ธ์ฆ์ ์ฝ๊ณ ๋น ๋ฅด๊ฒ ๊ด๋ฆฌํ ์ ์๋๋ก ํ๋ค.
- ์ฌ์ฉ์๋ Google ๊ณ์ ์ ๋ก๊ทธ์ธํ๊ณ ๋์ํ๋ฉฐ ํ๋กํ ์ ๋ณด๋ฅผ ์์ ํ๊ฒ ํ๋ซํผ๊ณผ ๊ณต์ ํ๋ค.
- Google ๊ณ์ ์ ์ด์ฉํ ์๋น์ค ๊ฐ์ ์ด๋, Google ๊ณ์ ์์ ์์ ํ๋กํ ์ ๋ณด๋ฅผ ํ๋ซํผ๊ณผ ๊ณต์ ํ๊ธฐ ์ํ ๋์๋ฅผ ์ป๋ ๋จ๊ณ์ด๋ค.
- ์ผ๋ฐ์ ์ผ๋ก ์ด ๊ณต์ ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ์ฌ ์๋น์ค์ ์ ๊ณ์ ์ด ์์ฑ๋์ง๋ง ํ์์ ์ด์ง๋ ์๋ค.
- ๋ก๊ทธ์ธ์ด๋, ์ด๋ฏธ Google ๊ณ์ ์ ์ด์ฉํ์ฌ ์๋น์ค ๊ฐ์ ์ ๋ง์น ์ฌ์ฉ์์ ๊ฒฝ์ฐ ํ์ฑ Google ๊ณ์ ์ ์ฌ์ฉํ์ฌ ์น ์๋น์ค์ ๋ก๊ทธ์ธํ๋ ๊ฒ์ ์๋ฏธํ๋ค.
Google Login Flow ( ์ฐ๋ฆฌ ์น ์๋น์ค์ ๊ฒฝ์ฐ)
1. Google API Console ์ ์ฌ์ฉ์ ์ธ์ฆ ์ ๋ณด ํญ์์ OAuth 2.0 client ์ ๋ณด ์์ฑ ๋๋ ํ์ธ. (clientId)
2. web-front ์ฝ๋์ gsi/client srcipt ์ฝ์ .
3. 1๋ฒ์ clientId ๋ฐ ์ฌ์ฉ์ ์ธ์ฆ์ ๋ํ ์๋ต callback์ google initialize์์ ์ธํ .
4. ๊ตฌ๊ธ ๋ก๊ทธ์ธ ๋ฒํผ์ ํด๋ฆญํ์ฌ ๋ฐ์์ํฌ ํจ์๋ฅผ ๋ง๋ค๊ณ , Google์์ ์๋ต๋ฐ์ accessToken(credential)์ ์ด์ฉํ์ฌ, ์๋ฒ์์ google์ธก์ ํ ํฐ ์ ํจ์ฑ ๊ฒ์ฌ ํ ์ฌ์ฉ์ ์ ๋ณด๋ฅผ ์์ฒญํ์ฌ ์๋ต์ ๋ฐ์.
5. ์๋ต ๋ฐ์ ์ฌ์ฉ์ ์ ๋ณด๋ฅผ ํตํด ์น ์๋น์ค์ ํ์๊ฐ์ ์ ์งํ (์ด ๊ณผ์ ์์ ์น front๋จ์์ ์๋น์ค ์ด์ฉ ์ฝ๊ด ๋์ ๋ฑ์ ์ถ๊ฐ์ ์ผ๋ก ๋ฐ๋๋ค.)
6. ์น ์๋น์ค์ ํ์๊ฐ์ ๋ฐ ๋ก๊ทธ์ธ ์๋ฃ.
Google๋ก ๋ก๊ทธ์ธํ๊ธฐ ๋ฒํผ ๋ ธ์ถ ๋ฐฉ๋ฒ(๊ตฌ๊ธ์์ ์ง์ํ๋ ๋ก๊ทธ์ธ ๋ฒํผ ๋ ธ์ถ ๋ฐฉ๋ฒ)
1. ์ฝ๋์ gsi/client srcipt ์ฝ์
<script src="https://accounts.google.com/gsi/client" async defer></script>
2. clientId ๋ฐ ์ฌ์ฉ์ ์ธ์ฆ์ ๋ํ ์๋ต callback์ google initialize์์ ์ธํ ๋ฐ renderButton method๋ฅผ ์ด์ฉํ์ฌ ๊ตฌ๊ธ ๋ก๊ทธ์ธ ๋ฒํผ์ ๋ ๋๋ง ์์ผ์ค.
window.onload = function () {
google.accounts.id.initialize({
client_id: "YOUR_GOOGLE_CLIENT_ID",
callback: handleCredentialResponse
});
google.accounts.id.renderButton(
document.getElementById("buttonDiv"),
{ theme: "outline", size: "large" } // customization attributes
);
google.accounts.id.prompt(); // also display the One Tap dialog
}
++ renderButtom ์์ฑ ๊ฐ ์ฐธ๊ณ
3. ์ ์ฒด ์ฝ๋
<html>
<body>
<script src="https://accounts.google.com/gsi/client" async defer></script>
<script>
function handleCredentialResponse(response) {
// response์ accessToken์ธ credential๊ฐ์ ์ป์ ์ ์๋ค.
console.log("Encoded JWT ID token: " + response.credential);
}
window.onload = function () {
google.accounts.id.initialize({
client_id: "YOUR_GOOGLE_CLIENT_ID",
callback: handleCredentialResponse
});
google.accounts.id.renderButton(
document.getElementById("buttonDiv"),
{ theme: "outline", size: "large" } // customization attributes
);
google.accounts.id.prompt(); // also display the One Tap dialog
}
</script>
<div id="buttonDiv"></div>
</body>
</html>
++ ์ฐธ๊ณ - initialize ์์ฑ ๊ฐ.
google.account.id.initialize({ client_id, callback })
google.accounts.id.initialize ์ค์ ๊ฐ
Next.js๋ฅผ ์ด์ฉํ Google Login ๊ตฌํ ์ฝ๋ ( ์ฝ๋ ์์ )
import React, { useRef } from 'react';
import { GOOGLE_CLIENT_ID } from '../../../../common/const';
import useSocialLogin from '../../../../utils/useSocialLogin';
interface GoogleLoginProviderProps {
children?: any;
}
const GoogleLoginProvider = ({ children }: GoogleLoginProviderProps) => {
const googleRef = useRef<HTMLDivElement>();
// ํด๋น ๋ถ๋ถ์ ๊ฐ ์์
๋ก๊ทธ์ธ๋ณ response accessToken๋ฅผ ๋ฐ์์ ์ฐ๋ฆฌ ์๋ฒ์ ๋ณด๋ด์ฃผ๋ ์ปค์คํ
hook.
const { responseCallback } = useSocialLogin({ socialId: 'google' });
useEffect(() => {
const script = document.createElement('script');
script.src = 'https://accounts.google.com/gsi/client';
document.body.appendChild(script);
script.onload = () => {
const { google } = window as any;
const redirectUrl = `${location.origin}/login`;
google.accounts.id.initialize({
client_id: GOOGLE_CLIENT_ID,
callback: onSignIn,
auto_select: false,
login_uri: redirectUrl,
});
google.accounts.id.renderButton( googleRef.current, {
theme: "outline", size: "large" });
};
}, []);
const onSignIn = async (res) => {
await responseCallback({accessToken: res.credential});
};
return (
<div style={{position: 'relative'}}>
<!-- ๋๋ ์ปค์คํ
๋์์ธ ๋ฒํผ ์ฌ์ฉ์ ์ํด, ์ค์ google-login-button์ css๋ก ๋ณด์ด์ง ์๊ฒ ์ฒ๋ฆฌํด์ฃผ์๋ค. -->
<div
id="google-login-button"
ref={googleRef}
style={{ opacity: 0, position: 'absolute', zIndex: 100, left: 0, top: 0, right:0, bottom: 0 }}
/>
<div>
{children}
</div>
</div>
);
};
export default GoogleLoginProvider;
++ ์ฐธ๊ณ - responseCallback์์๋ ํ๋ผ๋ฏธํฐ์ accessToken ๊ฐ๊ณผ socialId ๊ฐ์ ๋ฐ์์, ์ฐ๋ฆฌ ์๋น์ค์ ๋ก๊ทธ์ธ ๋ก์ง์ ํ์ ๋ก๊ทธ์ธ์ ์๋ํ๊ณ , ์ฌ์ฉ์ ๊ณ์ ์ ๋ณด๊ฐ ์์ ์(์๋น์ค์ ํ์ ๊ฐ์ ํ ์ ์ ๊ฐ ์๋ ๊ฒฝ์ฐ) ํ์ด์ง redirect๋ฅผ ํตํด ํ์ ๊ฐ์ ์ ๋ก์ง์ ํ๊ฒ ๋๋ค.
๐ธ ์ถ์ฒ ๐ธ
'React' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[ webpack ] React(๋ฆฌ์กํธ)์ webpack(์นํฉ) (0) | 2023.03.05 |
---|---|
[ React ] React Element ์ Component์ ์ฐจ์ด์ (0) | 2023.02.24 |
[ React / Redux ] Redux ์ํ ๊ด๋ฆฌ ๊ฐ๋ ์ ๋ฆฌ. (0) | 2022.09.25 |
[ NEXT.JS ] Next.js์ ๋ํด ์์๋ณด๊ธฐ. (0) | 2022.09.18 |
[ React / Recoil ] React์ ์ํ๊ด๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ Recoil์ effects ์ฌ์ฉํ๊ธฐ. (0) | 2022.07.11 |