🪁 API 연동
1. fetch
- HTTP 요청을 보내는 데 사용되는 도구
- 브라우저에서 기본적으로 제공하는 API
- 따로 설치할 필요 없음
const getData = async () => {
const response = await fetch("url")
const data = await response.json();
}
2. axios
- HTTP 요청을 보내는 데 사용되는 도구
- 따로 라이브러리를 설치해야 함
- 자동으로 json을 적용하여 response 객체를 바로 반환 (편리)
- fetch에서는 없는 기능들 제공
const getData = async () => {
const { data } = await axios.get("url");
}
3. CRUD
- POST : 데이터 추가
- PUT : 데이터 수정 (데이터 식별을 위한 고유 아이디를 제외한 모든 데이터 수정)
- PATCH : 데이터 수정 (일부 내용만 수정)
- DELETE : 데이터 삭제
🪁 JWT Token
1. 로그인 및 토큰 데이터를 전역 상태로 관리
import { create } from "zustand";
interface AuthStore {
isLoggedIn: boolean;
accessToken: string | null;
login: (accessToken: string) => void;
logout: () => void;
}
export const useAuthStore = create<AuthStore>((set) => ({
isLoggedIn: false,
accessToken: null,
login: (accessToken: string) => set({ isLoggedIn: true, accessToken }),
logout: () => set({ isLoggedIn: false, accessToken: null }),
}));
2. 액세스 토큰을 API 요청에 액세스 토큰 담아 전송
export const axiosInstance = axios.create({
baseURL: `${import.meta.env.VITE_API_URL}`,
withCredentials: true,
});
axiosInstance.interceptors.request.use((config) => {
const token = useAuthStore.getState().accessToken;
if (token) {
config.headers["Authorization"] = `Bearer ${token}`;
}
return config;
});
3. 액세스 토큰이 없어 에러가 발생, 리프레시 토큰으로 재발급하고 재요청
let retry = false;
axiosInstance.interceptors.response.use(
(response) => response,
async (error) => {
const originalRequest = error.config;
if (error.response?.status === 403 && !retry) {
console.log("token 실패");
retry = true;
try {
const { data } = await axiosInstance.post("/token");
console.log(data);
useAuthStore.setState({
accessToken: data.accessToken,
isLoggedIn: true,
});
originalRequest.headers["Authorization"] = `Bearer ${data.accessToken}`;
return axiosInstance(originalRequest);
} catch (err) {
console.log(err);
}
}
}
);
4. 새로고침하면 전역 상태로 관리하던 액세스 토큰이 날라가는 문제
- 리프레시 토큰으로 액세스 토큰 다시 받아오기
- App.tsx에서 useEffect를 이용해 첫 렌더링 시, 토큰 발급하는 api 호출
5. 리프레시 토큰을 API 요청에 함께 보내는 방법
withCredentials
: HTTP 요청에서 쿠키, 인증 헤더, 도는 기타 자격 증명을 포함하도록 설정하는 옵션
- axios에서 withCredentials를 true로 설정하면, 클라이언트와 서버 간의 요청에 자격 증명 포함 가능
- 자격 증명을 필요로 하는 경우에만 true로 설정 (리프레시 토큰 받을 때, 보낼 때)
- 이 방식 말고
- Authorization 헤더에 토큰을 담아 전송하는 방식도 있음
6. Private Route 구현
- 로그인 여부에 따라 유저의 접근을 제한해야 하는 경우
import { useEffect, useState } from "react";
import { Outlet, useNavigate } from "react-router";
import { useAuthStore } from "../stores/authStore";
export default function Private() {
const navigate = useNavigate();
const [show, setIsShow] = useState(false);
const isLoggedIn = useAuthStore((state) => state.isLoggedIn);
useEffect(() => {
if (!isLoggedIn) {
navigate("/login");
return;
}
setIsShow(true);
}, []);
return <>{show && <Outlet />}</>;
}
📌 출처
수코딩(https://www.sucoding.kr)