아주 많고 많은 블로그들을 참고했지만, 유튜브도 참고했지만.. 카카오톡 로그인에 대해서 상세히 기술해놓은 블로그가 없어서.. 그래.. 내가 적자..하고 적는 블로그입니다. ^_^;; 벨로퍼트님의 블로그도 참고해보았지만 저의 수준에서는 이해하기 어려웠읍니다.. passport 미들웨어를 사용하셨는데, 이를 우째 사용해야하는지 1도 모르겟어서 passport를 이용하지 않고 로그인을 구현할 수 없을까? 하고 적는 게시글입니다.
● 카카오 디벨로퍼스
먼저 위에 블로그를 보고 디벨로퍼스에서 세팅을 해줍니다.
저는 아래와 같이 설정하였습니다.
- 애플리케이션 URL : http://localhost:3000
- 리다이렉트 : http://localhost:3000
● 인증이 이루어지는 과정
● 서버와 클라이언트 구분해서 만들기
먼저 디렉토리 하나를 만들어주세요, 저는 kakaologin이라는 파일을 만들겠습니다.
npx create-react-app client
먼저 client 프로젝트를 하나 만들어줍니다.
그 다음 서버 디렉토리를 만들어주세요.
mkdir server
먼저 서버쪽으로 돌아와서, 필요한 모듈부터 깔아주겠습니다.
꼭 디렉토리를 서버쪽으로 옮겨주셔야합니다!
cd server
서버쪽으로 옮긴 후, npm init을 해주세요.
npm init -y
다음 아래 모듈들을 모두 깔아주시면됩니다.
npm i -D morgan nodemon
npm i cors axios cookie-parser express
방금 설치한 모듈들의 설명을 알고 싶다면 아래 포스팅을 참고해주세요.
다음 서버쪽에 디렉토리 최상단에 app.js 를 만들어주세요.
경로 : server > app.js
app.js
const express = require('express');
const morgan = require('morgan');
const cookieParser = require('cookie-parser');
const cors = require('cors');
const controllers = require('./controllers')
const app = express(); // express 프레임워크 사용
app.use(morgan('dev')); // 클라이언트 요청마다 콘솔에 로그가 찍힘
app.use(express.json()); // json 파싱알아서해줌
app.use(express.urlencoded({extended : false})); // 파라미터 파싱해주는거?인가 그럼
app.use(cookieParser()); // 쿠키 알아서 객체로 파싱해줌
// cors 설정
const corsOptions = {
origin : 'http://localhost:3000',
credentials : true,
methods : ['GET', 'POST', 'OPTIONS']
}
// cors 적용
app.use(cors(corsOptions));
// 라우팅 해줌
app.post('/callback', controllers.callback);
app.post('/userInfo', controllers.userInfo);
// 서버 포트열어줌
app.listen(4000 , ()=>{
console.log(`
**🙉 server is listening on 4000 ...**
`)
})
경로 : server > package.json
package.json
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "nodemon app.js" // 추가해주세요
},
서버쪽 package.json 위와 같이 수정해주세요. start 추가해주는거임
● 서버디렉토리 파일구성
일단 이렇게 만드셈 (logout.js는 구현하지 않았습니다. 만들지마세요)
그다음에, controllers에 있는 index.js를 아래와 같이 적어줍니다.
경로 : server > controllers > index.js
index.js
module.exports = {
callback: require('./users/callback'),
userInfo: require('./users/userInfo'),
};
● 클라이언트쪽 파일구성
추가된거는 Login.js, Mypage.js 밖에 없음 최대한 수정안보고 쉽게 만들려했습니다.
❍ 인증이 이루어지는 과정 - (1) 야 로그인한다 / (2) access 코드 전달받기
먼저 Login.js로 와줍니다.
경로 : client > src > Login.js
Login.js
export default function Login (){
const getAccessCode = () => {
return window.location.assign(`https://kauth.kakao.com/oauth/authorize?response_type=code&client_id=${당신의 REST API 코드를 입력하십시오.}&redirect_uri=http://localhost:3000`
);
}
return (
<div>
<button onClick={getAccessCode}>로그인하기 ㅋ</button>
</div>
)
}
****코드 중간에 REST API 입력하세요****
❍ 인증이 이루어지는 과정 - (3) 야 토큰가져와 / (4) 형님 토큰주십시오./ (5) 토큰 여기있다. / (6) 토큰 전달드립니다.
그다음, App.js 파일로와주세요.
경로 : client > src > App.js
App.js
import axios from 'axios';
import { useEffect, useState } from 'react';
import Login from './Login';
import Mypage from './Mypage';
export default function App (){
const [isLogin,setIsLogin] = useState(false);
const [accessToken, setAccessToken] = useState('');
axios.defaults.withCredentials = true;
// (3) 서버쪽으로 access 코드를 보내고, access Token을 가져옵니다.
// Token을 가져오면 accessToken이라는 state에 저장해줍니다.
const getAccessToken = async (authorizationCode) => {
return axios.post('http://localhost:4000/callback', {authorizationCode})
.then(res => {
setAccessToken(res.data);
setIsLogin(true);
})
.catch(err => {
console.log(err.response.data);
})
};
// (2) access 코드를 가지고 리다이렉팅 되면 서버쪽으로 요청을 시작합니다.
// access 코드가 있다면, getAccessToken 함수를 실행합니다.
useEffect(() => {
const url = new URL(window.location.href);
const authorizationCode = url.searchParams.get('code');
if (authorizationCode) {
getAccessToken(authorizationCode);
}
}, []);
return (
<div>
{
isLogin ? <Mypage accessToken={accessToken} setIsLogin={setIsLogin}/> : <Login/>
}
</div>
)
}
그다음 서버쪽으로 돌아옵니다.
서버에서 users > callback.js로 와줍니다.
경로 : server > controllers > users > callback.js
callback.js
const axios = require('axios');
const CLIENT_ID = '당신의 REST API KEY를 입력하십시오. 필수입니다. 수정보세요.';
module.exports = async (req, res)=> {
// 클라이언트에서 받아온 access code를 불러옵니다.
const { authorizationCode } = req.body;
try {
// 다음 카카오 auth 서버에 access code를 보내 token을 받아옵니다.
const result = await axios({
method: 'POST',
url: `https://kauth.kakao.com/oauth/token`,
headers:{
'content-type':'application/x-www-form-urlencoded'
},
data: {
grant_type: 'authorization_code',
client_id: CLIENT_ID,
redirect_uri : 'http://localhost:3000',
code: authorizationCode,
},
});
// 토큰을 받아져왔으면 클라이언트에게 전달해줍니다.
const accessToken = result.data.access_token;
return res.status(200).send({ accessToken });
} catch (err) {
console.log(err);
}
}
****코드 중간에 REST API 입력하세요****
❍ 인증이 이루어지는 과정 - (7) 내정보가져와 임마! / (8) 정보 주십시요 행님 / (9) 정보여깃다 / (10) 정보 전달드립니다
이제, token을 가져왔으니, 클라이언트측에서 정보를 요청합니다.
클라이언트 쪽인 Mypage.js로 와줍니다.
경로 : client > src > Mypage.js
Mypage.js
import { useEffect, useState } from 'react'
import axios from 'axios';
export default function Mypage ({setIsLogin, accessToken}){
const [userData, setData ] = useState(null);
const [isLoading, setIsLoading] = useState(true);
console.log(userData);
// Mypage가 렌더링 되면 바로 accessToken을 보내주고 정보를 가져오라고 서버에 요청합니다.
// 정보를 가져오게 되면, userData라는 state에 저장해줍니다.
useEffect(()=>{
axios.post('http://localhost:4000/userInfo', {accessToken})
.then(res => {
setData(res.data);
setIsLoading(false);
});
}, [])
return(
<div>
<h2>마이페이지</h2>
{
isLoading ?
<h4>잠시만 기다려주세요...</h4> :
<div>
<h3>{userData.profile.nickname}</h3>
<p>{userData.email}</p>
<img src={userData.profile.thumbnail_image_url}/>
</div>
}
</div>
)
}
다음 서버쪽으로 돌아와줍니다.
이제 서버가 카카오 resource server에 유저정보 달라고 요청합니다.
경로 : server > controllers > users > userInfo.js
userInfo.js
const axios = require('axios');
module.exports = async (req, res) => {
// 클라이언트가 준 accessToken을 가져옵니다.
const { accessToken } = req.body;
// 유저정보를 토큰과 함께, 카카오 resource 서버에 요청합니다.
return axios
.get('https://kapi.kakao.com/v2/user/me', {
headers: {
Authorization: `Bearer ${accessToken.accessToken}`,
},
})
.then(response => { // 정상적으로 유저정보를 받아오면 응답에 넘겨줍니다.
res.send(response.data.kakao_account);
})
.catch(err => {
console.log(err);
})
};
그럼 위와 같은 모습이 됩니다!
조금더 알고 싶다면 아래 공식 문서를 읽어보는 것을 추천드립니다.
저도 증~맬로 읽기 싫었찌만.. 역시 다른 블로그를 참고하는 것보다 공식문서가 최고라는걸 깨달았읍니다..
다른 블로그 보는 것보다 공식문서를 읽는 것이 가장 빠를 겁니다!