“ 당신은 소프트웨어 품질을 추구할 수도 있고, 포인터 연산을 할 수도 있다. 그러나 두 개를 동시에 할 수는 없다. ”
안녕하세요. 요즘 회사가 너무 바빠지다 보니 개발 관련 포스팅 올리는 게 쉽지가 않네요 ㅠ..
점점 더워지는데 다들 몸 관리 잘하시고 열심히 같이 공부 한번 진행해 봅시다!
이번 포스팅 주제는 "FrontEnd에서 카카오 인가 코드 받아서 사용자 정보 받아보기"입니다.
이전에 React와 Nuxt로 카카오 로그인 과정과 방법에 대해서 설명을 해봤는데요.
카카오 Developers 내 애플리케이션에서 도메인과 redirect URI를 프런트 정보로 등록하여, 인가코드를 받고
여기까지 하면 프런트가 할 일은 다했다!라고 끝낸 포스팅이 있습니다.
만약에 이 과정을 못 보셨다면 아래 링크를 통해서 한번 읽어주시면 감사하겠습니다!!
[Nuxt] 카카오 로그인 OAuth 신청 및 설정 - ①
아무튼 프런트에서 할 일이 끝났다면 이제 서버에서 그 과정을 이어서 처리하는 방법에 대해서 설명해 볼까 합니다.
서버 환경
- express
- typescript
프런트에서 발급받은 인가코드로 서버에서 사용자 정보를 조회하는 기능을 구현해 보는 것이기 때문에 환경은 그렇게 크게 영향이 없어 간단하게 어떤 서버로 구현하는 건지만 작성했습니다! NodeJS express 서버로 한번 구현해 보도록 해보겠습니다.
카카오 로그인 과정 - Rest api Key
아래 이미지에 과정으로 프런트 엔드에서 인가코드까지 발급을 받아서 서버로 보낸 상태를 가정하여 진행해 보도록 하겠습니다.
먼저 카카오 Developers에서 아래 이미지와 같이 앱키를 볼 수 있는데 여기서 Rest API 키와 , JavaScript 키를 사용합니다.
Express Router 구현
express 설치하고 뭐 이것저것 세팅하고, 마지막 app.listen으로 서버 포트까지 콘솔로 보신 분들만 진행해주세요!
express 설치와 셋팅 과정이 미흡 하시다면 아래 포스팅에서 과정을 진행하고 보시면 될거같습니다!
TypeScript(타입스크립트) Express API 서버 - 환경셋팅
- 위에 이미지 과정대로 auth/kakao URL로 구현합니다.
- api/routes 폴더에 auth.ts 파일에 작성합니다.
import {Router} from "express";
export default (router:Router)=>{
router.use('/auth',router) // "/auth"가 기준이됨
router.post('/kakao',async (req,res,next)=>{ //라우터 구현
})
}
- 물론 api/index.ts 경로에 위에 auth.ts를 등록 합니다.
import {Router} from 'express'
import auth from './routes/auth.route'
export default ()=>{
const app = Router()
auth(app)
return app
}
이유는 제 위에 포스팅을 보시면 저는 이런 구조로 구현 했기 때문에 비슷한 방식으로 구현하려고 합니다. 굳이 이렇게 분할 해서 안하셔도되고 본인의 개발 스타일에 따라 다르게 구현하셔도됩니다. 그냥 세부 기능동작만 참고하시면 될거같습니다.
카카오 인가코드로 엑세스 토큰 발급 받기
- 프런트에서 axios post요청으로 아래처럼 보낸다고 가정해봅니다.
//TODO: 소셜로그인 - kakao
export function kakaoSignIn(code:string)
{
return new Promise(async (resolve,reject)=>{
await post(`/auth/kakao`,code)
.then((data)=>{
resolve(data)
})
.catch((error)=>{
reject(error)
})
})
}
- express 서버에 auth.ts에 구현한 auth 라우터로 위에 있는 인가코드를 받습니다.
import {Router} from "express";
export default (router:Router)=>{
router.use('/auth',router)
router.post('/kakao',async (req,res,next)=>{
const {code} = req.body // 프런트에서 인가코드 body에 담아서 보낸거 받기
})
}
- PostMan으로 확인해보니 잘 나옵니다. 이러면 위에 구현한 라우터가 잘 동작한다는것을 알수있습니다.
- 이제 실질적으로 body로 통해 들어온 "code"로 카카오 엑세스 토큰을 요청합니다.
import {Router} from "express";
import * as console from "console";
import axios from 'axios'
interface Data {
grant_type: string;
client_id: string;
code: string;
[key: string]: string;
}
export default (router:Router)=>{
router.use('/auth',router)
router.post('/kakao',async (req,res,next)=>{
const {code} = req.body // 프런트에서 인가코드 body에 담아서 보낸거 받기
const restApiKey = '123' // 앱키 - Rest API key
const data :Data={
grant_type:'authorization_code',
client_id:restApiKey,
code
}
// 헤더 설정
const header = {
'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8',
'Authorization': 'Bearer '
};
// grant_type=authorization_code&client_id=your_client_id&code=authorization_code_here
// 위에 처럼 문자열 형태로 구성하기 위해
const queryString = Object.keys(data)
.map(k=>encodeURIComponent(k)+'='+encodeURIComponent(data[k]))
.join('&')
const kakaoToken = await axios.post("https://kauth.kakao.com/oauth/token", queryString, {headers: header})
console.log(kakaoToken)
})
}
- 코드 마지막을 확인하면 카카오 쪽 URL로 post 요청을 하여 KakaoToken 변수에 담는데 그 결과가 아래와 같습니다.
- 여기서 저희는 "access_token" 이 데이터만 사용합니다.
카카오 엑세스 토큰으로 사용자 정보 조회 하기
- 자! 이제 끝이 보입니다. 위에 access_token을 헤더에 담고 카카오 사용자 정보 조회하는 URL로 get요청을 해봅니다.
import {Router} from "express";
import * as console from "console";
import axios from 'axios'
interface Data {
grant_type: string;
client_id: string;
code: string;
[key: string]: string;
}
const header = {
'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8',
'Authorization': 'Bearer '
};
export default (router:Router)=>{
router.use('/auth',router)
router.post('/kakao',async (req,res,next)=>{
const {code} = req.body // 프런트에서 인가코드 body에 담아서 보낸거 받기
const {accessToken}=await getKakaoToken(code)
const {id,email} = await getUserInfo(accessToken)
console.log(id,email)
})
const getKakaoToken = async (code:string)=>{
const restApiKey = '123' // 앱키 - Rest API key
const data :Data={
grant_type:'authorization_code',
client_id:restApiKey,
code
}
const queryString = Object.keys(data)
.map(k=>encodeURIComponent(k)+'='+encodeURIComponent(data[k]))
.join('&')
// 카카오 토큰 요청
const token = await axios.post("https://kauth.kakao.com/oauth/token", queryString, {headers: header})
// 엑세스 토큰 발급
return {accessToken:token.data.access_token}
}
const getUserInfo = async (accessToken:string)=>{
// Authorization: 'Bearer access_token'
// 엑세스 토큰 헤더에 담기
header.Authorization +=accessToken
// 카카오 사용자 정보 조회
const get = await axios.get("https://kapi.kakao.com/v2/user/me", {headers: header})
const result = get.data
// id, email 추출
return {id:result.id,email:result.kakao_account.email}
}
}
라우터 내에서 "엑세스 토큰 발급받는 기능" ,"엑세스 토큰으로 사용자 정보 조회 기능" 이렇게 함수를 만들어서 구현했는데 좀더 깔끔하게 하기 위해서는 미들웨어로 빼서 사용하면 좋을거 같습니다! 한번 시도해보세요! 만약에 혹시 햇갈리신다면 다음 포스팅에서 미들웨어까지 한번 해보겠습니다! 그러면 이제 아래와 같은 이미지 처럼 사용자 데이터가 나옵니다. 물론 정보 제공동의 같이 사용자 동의가 된 정보를 얻을 수 있습니다. 이제 여기 데이터를 활용하여 정보를 db에 저장하고 본인 웹사이트 토큰(jwt)을 사용자에게 발급해주면 됩니다.
이번 포스팅에서 카카오 앱 키중 Rest API 키로 "프런트에서 요청하여 넘겨받은 "인가코드" 로 서버에서 카카오 토큰을 요청하여 access_token을 발급받고, 그 access_token을 헤더에 삽입하여 카카오 사용자 정보를 조회하는 거 까지 마무리 했습니다.
다음 포스팅에서는 JavaScript Key로 프런트에서 어디까지 작업한 내용으로 서버에서 어떻게 구현할지 한번 포스팅 해보겠습니다! 그러면 읽어주셔서 감사하고, 댓글 부탁드립니다.