반응형
React + TypeScript를 사용해서 카카오 로그인을 구현해 봤습니다.
Next.js를 이용해서 개발을 진행하였습니다.
카카오 로그인 과정
1. 카카오 SDK 자바스크립트 불러오기
<script src="https://t1.kakaocdn.net/kakao_js_sdk/2.4.0/kakao.min.js"
integrity="sha384-mXVrIX2T/Kszp6Z0aEWaA8Nm7J6/ZeWXbL8UpGRjKwWe56Srd/iyNmWMBhcItAjH" crossorigin="anonymous"></script>
<script>
2. 카카오 SDK 초기 설정
Kakao.init(JAVASCRIPT_APP_KEY);
3. 로그인 요청
Kakao.Auth.authorize({
redirectUri: "http://localhost:3000/login",
});
로그인이 성공하게 되면 redirectUri에서 설정한 주소로 코드 값이 옵니다.
ex) http:/// localhost:3000/login?code=12345
4. 코드 값을 보내서 토큰 받아오기
const response = await fetch("https://kauth.kakao.com/oauth/token", {
method: "POST",
headers: {
"Content-type": "application/x-www-form-urlencoded;charset=utf-8",
},
body: `grant_type=authorization_code&client_id=${REST_API_KEY}&redirect_uri=http://localhost:3000/login&code=${req.query.code}`,
});
5. 토큰 값 설정하기
Kakao.Auth.setAccessToken(accessToken);
토큰 값을 설정하게 되면 사용자 정보를 가져올 수 있습니다.
6. 사용자 정보 가져오기
Kakao.API.request({
url: "/v2/user/me",
});
위의 일련의 과정을 거쳐서 카카오 로그인이 성공하게 되고, 유저정보를 가져올 수 있습니다.
React 코드
저는 Next.js에서 React + TypeScript를 이용해서 구현해 보았습니다.
pages/api/getKakoLogin.ts
Kakao.Auth.authorize 호출 이후 redirect를 통해서 받은 code를 token으로 받는 함수입니다.
import type { NextApiRequest, NextApiResponse } from "next";
const REST_API_KEY = "YOUR_REST_API_KEY";
export default async function handler(
req: NextApiRequest,
res: NextApiResponse,
) {
if (req.method === "POST") {
const response = await fetch("https://kauth.kakao.com/oauth/token", {
method: "POST",
headers: {
"Content-type": "application/x-www-form-urlencoded;charset=utf-8",
},
body: `grant_type=authorization_code&client_id=${REST_API_KEY}&redirect_uri=http://localhost:3000/login&code=${req.query.code}`,
});
const data = await response.json();
res.status(200).send({ data });
}
}
login/index.tsx
import { Fragment, useEffect, useState } from "react";
import { useRouter } from "next/router";
declare global {
interface Window {
Kakao: any;
}
}
interface IuserInfo {
nickName: string;
email?: string;
profileImagePath?: string;
}
const KAKAO_SDK_URL = "https://developers.kakao.com/sdk/js/kakao.js";
const JAVASCRIPT_APP_KEY = "YOUR_JAVASCRIPT_APP_KEY";
export default function KakaoLogin() {
const router = useRouter();
const [code, setCode] = useState<string | string[] | undefined>(undefined);
const [isLogin, setIsLogin] = useState<Boolean>(false);
const [userInfo, setUserInfo] = useState<IuserInfo>({
nickName: "",
});
useEffect(() => {
const script = document.createElement("script");
script.src = KAKAO_SDK_URL;
script.async = true;
document.body.appendChild(script);
script.onload = () => {
window.Kakao.init(JAVASCRIPT_APP_KEY);
};
}, []);
async function loginWithKakao() {
await window.Kakao.Auth.authorize({
redirectUri: "http://localhost:3000/login",
});
}
useEffect(() => {
const getToken = async (code: string | string[] | undefined) => {
const response = await getLoginToken(code);
return response.data.access_token;
};
const setAccessToken = async (accessToken: string) => {
if (accessToken) {
if (window.Kakao.Auth) {
await window.Kakao.Auth.setAccessToken(accessToken);
}
setIsLogin(true);
} else {
setIsLogin(false);
}
};
const getUserInfo = async () => {
if (!code) {
return;
}
const accessToken = await getToken(code);
if (accessToken) {
await setAccessToken(accessToken);
}
if (isLogin) {
const response = await window.Kakao.API.request({
url: "/v2/user/me",
});
setUserInfo({
nickName: response.properties.nickname,
email: response.kakao_account.email,
profileImagePath: response.properties.profile_image,
});
}
await router.push("/login");
};
if (router.query.code !== code) {
setCode(router.query.code);
}
getUserInfo();
}, [router.query.code, code]);
async function getLoginToken(code: string | string[] | undefined) {
const response = await fetch("/api/getKakaoLoginToken?code=" + code, {
method: "POST",
});
return await response.json();
}
return (
<Fragment>
<h1>Kakao Login</h1>
<a id="kakao-login-btn" onClick={loginWithKakao}>
<img
src="https://k.kakaocdn.net/14/dn/btroDszwNrM/I6efHub1SN5KCJqLm1Ovx1/o.jpg"
width="222"
alt="카카오 로그인 버튼"
/>
</a>
<h2>{isLogin ? "Success" : ""} </h2>
<h2>{userInfo.email}</h2>
<h2>{userInfo.nickName}</h2>
<img
src={userInfo.profileImagePath}
alt="profile image"
width="250px"
height="250px"
/>
</Fragment>
);
}
카카오 로그인 성공 화면
728x90
반응형