현재 오즈코딩스쿨 강의를 통해 프론트엔드를 학습하고 있습니다.
본 포스트는 해당 강의에 대한 내용 정리를 목적으로 합니다.


OAuth는 사용자의 비밀번호를 직접 공유하지 않고도 제3자 애플리케이션이 사용자 자원에 접근할 수 있도록 허용하는 인증 및 권한 부여 프로토콜이다.
OAuth는 보안성과 편의성을 동시에 확보하기 위한 수단이다. ID와 비밀번호를 직접 입력받는 대신, 권한을 위임하는 방식으로 작동하므로 사용자의 개인정보 유출 위험을 줄일 수 있다.



| 용어 | 설명 |
|---|---|
| Resource Owner | 리소스를 소유한 사용자이다. |
| Client | 사용자 대신 API에 접근하려는 제3자 애플리케이션이다. |
| Authorization Server | 인증을 처리하고 Access Token을 발급하는 서버이다. |
| Resource Server | 보호된 리소스를 보관하고, Access Token을 통해 접근을 허용하는 서버이다. |
| Access Token | 일정한 권한과 유효기간을 가진 인증 토큰이다. |
npm init -y
npm i express cors axios
node server 서버 확인(터미널)
애플리케이션 추가



설정 > 카카오 로그인 ON



Redirect URI 입력



동의 항목 설정


-앱 설정 > 앱 키 > REST API 키 사용

비즈니스 인증 > 보안 > Client Secret

문서 > 카카오 로그인 > REST API


인가 코드


토큰 받기


사용자 정보 가져오기

로그아웃

문제점 error_code:'KOE320'

.then이 하나가 빠짐...ㅠㅠ
axios.post('http://localhost:3000/kakao/login', {authorizationCode})
.then((res) => { // 첫 번째 .then(): 인가 코드를 서버로 보내고 Access Token을 받는 단계
console.log(res); // 서버 응답 전체를 콘솔에 출력 (디버깅에 유용)
kakaoAccessToken = res.data; // 서버 응답 데이터를 kakaoAccessToken 변수에 할당.
// 만약 서버가 { accessToken: '...' } 형태로 응답한다면 res.data.accessToken으로 접근해야 합니다.
return axios.post('http://localhost:3000/kakao/userinfo', {kakaoAccessToken})
.then((res) => res) // 두 번째 .then(): 받은 Access Token으로 사용자 정보를 요청하는 단계
// 이 .then((res) => res) 부분은 불필요합니다.
})
.then(res => renderUserInfo(res.data.profile_image, res.data.nickname)) // 최종 .then(): 사용자 정보를 받아 UI를 렌더링하는 단계
}
추후 예정
login.js
const kakaoLoginButton = document.querySelector('#kakao')
const naverLoginButton = document.querySelector('#naver')
const userImage = document.querySelector('img')
const userName = document.querySelector('#user_name')
const logoutButton = document.querySelector('#logout_button')
function renderUserInfo(imgUrl = '', name = '') {
userImage.src = imgUrl
userName.textContent = name
}
const kakaoClientId = '7d91e2053ea405b28870316616b10058'
const redirectURI = 'http://127.0.0.1:5500'
let kakaoAccessToken = ''
// 카카오 로그인 버튼 클릭 시 로그인 페이지로 이동
kakaoLoginButton.onclick = () => {
location.href = `https://kauth.kakao.com/oauth/authorize?client_id=${kakaoClientId}&redirect_uri=${redirectURI}&response_type=code`
}
// 페이지 로드 후 인증 코드가 있으면 로그인 처리
window.onload = () => {
const url = new URL(location.href)
const authorizationCode = url.searchParams.get('code')
if (!authorizationCode) return // 인증 코드 없으면 중단
axios.post('http://localhost:3000/kakao/login', { authorizationCode })
.then(res => {
console.log('AccessToken 응답:', res)
kakaoAccessToken = res.data
return axios.post('http://localhost:3000/kakao/userinfo', { kakaoAccessToken })
})
.then(res => {
const { profile_image, nickname } = res.data
renderUserInfo(profile_image, nickname)
})
.catch(err => {
console.error('카카오 로그인 에러:', err)
})
}
// 로그아웃 버튼 클릭 시 처리
logoutButton.onclick = () => {
axios.delete('http://localhost:3000/kakao/logout', {
data: { kakaoAccessToken }
})
.then(res => {
console.log('로그아웃 성공:', res.data)
renderUserInfo('', '')
})
.catch(err => {
console.error('로그아웃 에러:', err)
})
}
server.js
const express = require('express')
const cors = require('cors')
const axios = require('axios')
const kakaoClientId = '7d91e2053ea405b28870316616b10058'
const redirectURI = 'http://127.0.0.1:5500'
const app = express()
app.use(cors({
origin: ['http://localhost:5500','http://127.0.0.1:5500'],
methods: ["OPTIONS", "POST", "DELETE"]
}))
app.use(express.json())
app.post('/kakao/login', (req, res) => {
const authorizationCode = req.body.authorizationCode
axios.post('https://kauth.kakao.com/oauth/token', {
grant_type: 'authorization_code',
client_id: kakaoClientId,
redirect_uri: redirectURI,
code: authorizationCode
},
{
headers: {'Content-Type' : 'application/x-www-form-urlencoded;charset=utf-8'}
}
)
.then(response => res.send(response.data.access_token))
})
app.post('/kakao/userinfo', (req, res) => {
const { kakaoAccessToken } = req.body
axios.get('https://kapi.kakao.com/v2/user/me', {
headers: {
Authorization: `Bearer ${kakaoAccessToken}`,
'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8'
}
})
.then(response => res.json(response.data.properties))
})
app.delete('/kakao/logout', (req, res) => {
const { kakaoAccessToken } = req.body
axios.post('https://kapi.kakao.com/v1/user/logout', {}, {
headers: {Authorization: `Bearer ${kakaoAccessToken}`}
})
.then(response => res.send('로그아웃 성공'))
})
app.listen(3000, () => console.log('서버 열림!'))