1. Axios란?
- Promise 기반 HTTP 클라이언트
- 브라우저와 Node.js에서 모두 사용 가능하며
fetch보다 직관적이고 기능이 풍부함
특징
- 요청/응답 인터셉터 지원
- 자동 JSON 변환
- 브라우저 호환성 우수
- baseURL, timeout, headers 등 기본 설정 가능
2. 설치
npm install axios
3. Axios 인스턴스 생성
// src/utils/axios.ts
import axios from "axios";
export const api = axios.create({
baseURL: process.env.NEXT_PUBLIC_API_URL || "https://api.example.com",
withCredentials: true, // 쿠키 인증 필요 시 true
});
// 요청 인터셉터
api.interceptors.request.use((config) => {
const token = localStorage.getItem("accessToken");
if (token) config.headers.Authorization = `Bearer ${token}`;
return config;
});
// 응답 인터셉터
api.interceptors.response.use(
(response) => response.data,
(error) => {
if (error.response?.status === 401) {
console.warn("인증 만료 → 로그인 페이지로 이동");
localStorage.removeItem("accessToken");
window.location.href = "/login";
}
return Promise.reject(error);
}
);
4. 인터셉터란?
axios.interceptors는 요청 또는 응답을 가로채어 중간에서 처리하는 미들웨어 같은 기능
axios.interceptors.request.use(요청가로채기함수);
axios.interceptors.response.use(응답가로채기함수);
주요 활용 예시
- 요청 전 토큰 자동 첨부
- 로딩 스피너 표시
- 공통 에러 처리 (401 시 자동 로그아웃 등)
5. config란?
config는 Axios가 실제 요청을 보낼 때 사용하는 설정 객체
- 꼭 config라는 변수 이름이어야 하는건 아님
axios.get("/users", { params: { page: 1 } });
{
method: "get",
url: "/users",
baseURL: "https://example.com/api",
headers: {
Accept: "application/json",
Authorization: "Bearer ..." // 우리가 인터셉터에서 추가할 수도 있음
},
params: { page: 1 },
data: undefined
}
6. 응답 인터셉터 구조
api.interceptors.response.use(
(response) => response.data, // 성공 시
(error) => Promise.reject(error) // 실패 시
);
- 성공 콜백 :
response.data만 반환해 편리하게 사용 가능
- 실패 콜백 : 에러 처리 후
Promise.reject(error)로 상위 호출부로 전달
- return Promise.reject(error)의 의미
- 만약 인터셉터에서 Promise.reject(error)를 반환하면
→ 이후 .catch나 try/catch에서 잡을 수 있음
Axios의 response 구조 예시
{
data: { id: 1, name: "가영" }, // 서버 응답 실제 데이터
status: 200, // HTTP 상태 코드
statusText: "OK",
headers: { ... },
config: { ... },
request: XMLHttpRequest {...}
}
Axios의 error 구조 예시
{
message: "Request failed with status code 401",
response: {
status: 401,
data: { message: "Unauthorized" },
headers: { ... }
},
config: { ... } // 요청 설정(config)
}
7. API 함수 모듈화
// src/utils/api/dashboard.ts
import { api } from "../axios";
export const dashboardApi = {
getAll: () => api.get("/dashboard"),
getById: (id: string) => api.get(`/dashboard/${id}`),
create: (data: { name: string }) => api.post("/dashboard", data),
update: (id: string, data: { name: string }) => api.put(`/dashboard/${id}`, data),
delete: (id: string) => api.delete(`/dashboard/${id}`),
};
8. 사용 예시
import { dashboardApi } from "@/utils/api/dashboard";
async function fetchDashboards() {
try {
const res = await dashboardApi.getAll();
console.log(res);
} catch (err) {
console.error(err);
}
}
9. Zustand와 함께 사용
// src/store/useDashboardStore.ts
import { create } from "zustand";
import { dashboardApi } from "@/utils/api/dashboard";
type Dashboard = { id: string; name: string };
type State = {
dashboards: Dashboard[];
fetchDashboards: () => Promise<void>;
};
export const useDashboardStore = create<State>((set) => ({
dashboards: [],
fetchDashboards: async () => {
const res = await dashboardApi.getAll();
set({ dashboards: res });
},
}));
10. 컴포넌트에서 사용
"use client";
import { useEffect } from "react";
import { useDashboardStore } from "@/store/useDashboardStore";
export default function MyDashboardPage() {
const { dashboards, fetchDashboards } = useDashboardStore();
useEffect(() => {
fetchDashboards();
}, [fetchDashboards]);
return (
<div>
{dashboards.map((item) => (
<div key={item.id}>{item.name}</div>
))}
</div>
);
}