(redirect_uri, 사이트 도메인 등록 방법을 다른 블로그에 많기 때문에 이 글에 따로 적지는 않겠다.)
카카오 로그인은 프론트, 서버 중 한쪽 사이드에서 모든 과정을 처리할 수 있다.
하지만 서버에서 모두 처리할 경우, 프론트에서 로그인을 요청했을 때 로그인 정보와 함께 리다이렉팅을 어떻게 할지 아이디어가 잘 떠오르지 않았다.
그리고 프론트에서 모두 처리할 경우, Kakao.Auth.login() 안에 Kakao.API.request() 함수 안에 axios 함수까지 써야 하기 때문에 콜백 지옥에 빠질 것 같아 서버에서 직접 사용자 정보를 가져오려 했다.
(Kakao.Auth.authorize()를 시도해봤지만 잘 안됐고, Kakao.Auth.login()에 파라미터로 success, fail을 넣어야 해서 async/await로 구현하는 건 더 복잡해질 수 있다고 판단했다)
npm i --save kakaojs axios js-cookie react-router-dom recoil
<!--index.html에 아래 태그 추가-->
<script src="https://developers.kakao.com/sdk/js/kakao.js"></script>
//index.js
...
import {RecoilRoot} from 'recoil';
ReactDOM.render(
<React.StrictMode>
<RecoilRoot> //recoil State
<App />
</RecoilRoot>
</React.StrictMode>,
document.getElementById('root')
);
// App.js
import Kakao from 'kakaojs';
import React from 'react';
import AppRouter from './Router';
function App(){
React.useEffect(( ) => {
window.Kakao.init('JavaScript 키'); // 배포할 땐 .env 파일에 넣어서 쓸 예정이다.
Kakao.isInitialized();
}, []);
return (
<div className="App">
<AppRouter />
</div>
);
};
//Router.js
import React from 'react';
import {BrowserRouter, Route, Switch } from "react-router-dom";
import SignUp from './SignUp';
import Home from './Home';
const AppRouter = () => {
return (
<BrowserRouter>
<Switch>
<Route exact path="/">
<Home />
</Route>
<Route path="/sign-up">
<SignUp />
</Route>
</Switch>
</BrowserRouter>
)
};
// Home.js
import axios from 'axios';
import Kakao from 'kakaojs';
import React from 'react';
import Cookies from 'js-cookie';
import ProfileState from './ProfileState';
import {useSetRecoilState} from 'recoil';
import { useHistory } from "react-router-dom";
const Home = () => {
const history = useHistory();
const setProfile = useSetRecoilState(ProfileState);
const signIn = () => {
axios.defaults.xsrfCookieName = "csrftoken"
axios.defaults.xsrfHeaderName = "X-CSRFToken" // 서버에 CSFR 토큰을 넘겨야 함.
Kakao.Auth.login({
scope: 'profile',
success: (res) => {
console.log('first res:', res)
Kakao.Auth.setAccessToken(res.access_token);
const csrftoken = Cookies.get('csrftoken');
axios.post('http://127.0.0.1:8000/account/login/kakao/', {
headers:{
"Access-Control-Allow-Origin": '*',
'Accept': 'application/json',
'Content-Type': 'application/json',
'X-CSRFToken': csrftoken
},
data: {
access_token: res.access_token
}
})
.then((res) => {
if (res.status === 203) { // 가입되지 않은 사용자일 경우 회원가입 부분으로 넘김
setProfile(res.data);
history.push("/sign-up");
} else if (res.status === 200) { // 가입된 사용자일 경우 로그인 성공 처리
window.alert("login completed");
}
})
.catch((err) => console.log(err))
},
fail: (err) => {
console.error(err);
}
});
};
return (
<div className="home">
<button onClick={signIn}>로그인</button>
</div>
);
};
// ProfileState.js
import {atom} from 'recoil';
const ProfileState = atom({
key: 'profileState',
default: {}
});
// SignUp.js
import React from "react";
import { useHistory } from "react-router-dom";
import axios from 'axios';
import Cookies from 'js-cookie';
import ProfileState from './ProfileState';
import {useRecoilValue} from 'recoil';
const SignUp = () => {
const history = useHistory();
const profile = useRecoilValue(ProfileState);
const [gSchoolNickname, setNickname] = React.useState('');
const signUp = () => {
const kakao_profile_info = profile.kakao_profile;
const csrftoken = Cookies.get('csrftoken');
axios.post('http://127.0.0.1:8000/account/sign-up/kakao/', {
headers:{
"Access-Control-Allow-Origin": '*',
'Accept': 'application/json',
'Content-Type': 'application/json',
'X-CSRFToken': csrftoken
},
data: {
kakao_id: profile.kakao_id,
g_school_nickname: gSchoolNickname, // 학교에서 사용하는 별명
kakao_nickname: kakao_profile_info.nickname,
profile_image: kakao_profile_info.thumbnail_image_url,
access_token: profile.access_token
}
})
.then((res) => {
history.push('/')
})
.catch((err) => console.log(err))
};
return (
<div>
<input type="text" value={gSchoolNickname} onChange={(e) => setNickname(e.target.value)} maxLength={2} />
<button onClick={signUp}>회원 가입</button>
</div>
)
};
아직 개발이 진행 중이기 때문에, 세부 설명들은 나중에 올릴게요..