[개념정리] Axios 완전 정복: 설치부터 인터셉터, Zustand 연동까지

짜장킴·2025년 8월 11일

프로젝트

목록 보기
10/38

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 } });
  • 내부적으로 다음과 같은 config를 생성함
{
  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>
  );
}
profile
프론트엔드 취준생입니다.

0개의 댓글