Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 |
Tags
- 이해할 수 있는
- 모던 자바스크립트 deep dive
- js
- IT 지식
- 비전공자를 위한
- 알고리즘
- 자격증
- SQL 개발자
- 노개북
- 프로그래머스
- SQLD
- 톺아보기
- 티스토리챌린지
- javascript
- 구름edu
- 노마드코더
- boj
- nomadcoders
- 공부를 가장한 일기일지도
- 자바스크립트
- 개발자북클럽
- 오블완
- 엘리스코딩
- 노마드 코더
- 백준
- Do it! 시리즈
- 제로베이스
- K-Digital Credit
- CodeStates
- 최원영 저자
Archives
- Today
- Total
개발자를 희망하는 초보의 자기개발 이야기
[카카오 로그인] 리액트로 카카오 로그인 구현하기 - 프론트엔드 (2) 본문
반응형
카카오 로그인 구현하기 - 프론트엔드 (2)
이전 글에서는 카카오 로그인 버튼을 만들고 로그인 페이지로 이동하는 과정을 다루었다. 이번 글에서는 인가 코드 처리 및 백엔드 연동을 이어서 다룬다.
1. 인가 코드 가져오기 (useSearchParams)
카카오 로그인 후 사용자는 인가 코드(authorization code) 를 Query String으로 받게 된다.
http://localhost:3000/callback?code=nuAFZmJvzl2a5Oz5acQckm8RzTmfSTea9y1SiczkbKjZNN9XyVDNeQAAAAQKPCPnAAABlXhW9uSi-KZYUq23DA
이제 이 인가 코드(nuAFZmJ...)를 백엔드에 전달하여 JWT 토큰을 받아야 한다.
import { useSearchParams } from "next/navigation";
const searchParams = useSearchParams();
const code = searchParams.get("code");
console.log("카카오 인가 코드:", code);
2. Axios 설정
백엔드와 API 요청을 할 수 있도록 axios를 설정한다.
import axios from "axios";
const api = axios.create({
baseURL: process.env.NEXT_PUBLIC_API_URL,
headers: {
"Content-Type": "application/json",
},
withCredentials: true, // 쿠키를 통한 토큰 처리시
});
export default api;
- withCredentials: true를 설정하면, 백엔드에서 쿠키를 통한 인증이 가능하다.
참고자료 : CORS로 쿠키 전송하기 (withCredentials 옵션)
3. 인가 코드 백엔드로 보내기
인가 코드를 백엔드로 보내서 JWT 토큰을 받아오는 API 요청 함수를 작성한다.
// src/services/authService.ts
import api from "@/lib/axiosInstance";
import { useAuthStore } from "@/store/authStore";
export const kakaoLogin = async (code: string) => {
try {
const response = await api.get(`/auth/kakao?code=${code}`);
const accessToken = response.headers["access"];
useAuthStore.getState().setAuth(accessToken);
return response.data;
} catch (error) {
console.error("카카오 로그인 실패:", error);
throw error;
}
};
- JWT 토큰을 Zustand를 이용해 저장할 예정이다.
- 우리팀은 토큰을 받을 때 헤더에 'access' 라는 키로 받기로 했었다.
4. Zustand로 로그인 상태 관리
Zustand를 이용하여 로그인 상태를 저장한다.
// src/store/authStore.ts
"use client";
import { create } from "zustand";
import { persist, createJSONStorage } from "zustand/middleware";
interface AuthState {
accessToken: string | null;
setAuth: (accessToken: string) => void;
logout: () => void;
}
export const useAuthStore = create<AuthState>()(
persist(
(set) => ({
accessToken: null,
setAuth: (accessToken) => set({ accessToken }),
logout: () => set({ accessToken: null }),
}),
{
name: "token",
storage: createJSONStorage(() => sessionStorage),
}
)
);
- Zustand의 persist 미들웨어를 사용하면 상태에 따라 세션 스토리지에 자동 저장된다.
5. Callback 페이지 구현 (KakaoCallback.tsx)
"use client";
import { useEffect } from "react";
import { useRouter, useSearchParams } from "next/navigation";
import { kakaoLogin } from "@/services/authService";
const KakaoCallback = () => {
const router = useRouter();
const searchParams = useSearchParams();
const code = searchParams.get("code");
useEffect(() => {
if (!code) {
console.error("카카오 로그인 실패: code 값 없음");
router.push("/main");
return;
}
const handleKakaoLogin = async () => {
try {
await kakaoLogin(code);
router.push("/home");
} catch (error) {
console.error("카카오 로그인 요청 실패:", error);
router.push("/main");
}
};
handleKakaoLogin();
}, [code, router]);
return <div>로그인 처리 중...</div>;
};
export default KakaoCallback;
- 로그인 성공 시 /home으로 이동, 실패 시 /main으로 돌아간다.
6. axios 인터셉터 설정
// src/lib/axiosInstance.ts
import axios from "axios";
import { useAuthStore } from "@/store/authStore";
const api = axios.create({
baseURL: process.env.NEXT_PUBLIC_API_URL,
headers: {
"Content-Type": "application/json",
},
withCredentials: true,
});
api.interceptors.response.use(
(response) => response,
async (error) => {
const originalRequest = error.config;
if (error.response?.status === 401 && !originalRequest._retry) {
originalRequest._retry = true;
try {
await api.post("/auth/refresh-token");
return api(originalRequest);
} catch (refreshError) {
console.error("토큰 갱신 실패, 로그아웃 필요:", refreshError);
useAuthStore.getState().logout();
window.location.href = "/main";
}
}
return Promise.reject(error);
}
);
export default api;
- 인터셉터를 통해 JWT 토큰이 만료되면 자동으로 갱신 요청을 한다.
7. 로그인 상태에 따른 UI 변경
"use client";
import { useAuthStore } from "@/store/authStore";
import KakaoLoginButton from "@/components/KakaoLoginButton";
export default function MainPage() {
const accessToken = useAuthStore((state) => state.accessToken);
return (
<div className="w-full flex justify-center items-center">
{accessToken ? <p>환영합니다!</p> : <KakaoLoginButton />}
</div>
);
}
- 로그인 여부에 따라 UI를 변경할 수 있다.
하지만 위의 방법은 세션 스토리지를 통해서 토큰을 관리하기 때문에 보안에 취약하다.
이어서 다음 글에서 withCredentials 설정과 HttpOnly 쿠키를 이용한 로그인 유지 방식을 진행한다.
반응형
'프론트엔드(Front-end)' 카테고리의 다른 글
[카카오 로그인] 리액트로 카카오 로그인 구현하기 - 프론트엔드 (1) (0) | 2025.03.06 |
---|---|
[카카오 로그인] Kakao Developers 설정 (1) | 2025.03.05 |
코딩 질문 잘하는 방법 (0) | 2024.08.22 |
자주 사용하는 마크다운 문법 12가지 (0) | 2024.08.05 |
웹의 주요 프로그래밍 언어 3가지 (2) | 2023.11.04 |