:ledger: Axios에 대해 알아보자.

이 글을 작성하기 전 개인,팀 과제를 통해 axios를 사용했다. 앞으로도 자주 사용될 것 같아서 머리속에 각인이 되길 바라는 마음으로 정리해보도록 한다.

:one: axios란 무엇인가?

  • node.js와 브라우저를 위한 Promise 기반 http 클라이언트
  • 즉, http를 이용해서 서버와 통신하기 위해 사용하는 패키지다.

:pushpin: 1-1) 특징

  1. promise 기반
    • 비동기 처리를 위한 promise를 지원하며 async/await와 함께 쉽게 사용할 수 있음
  2. JSON 데이터 자동 변환
    • 서버로부터 받은 JSON 데이터를 자동으로 변환해 처리할 수 있음
  3. 인터셉터(Interceptors)
    • 요청 또는 응답을 쌔벼서 특정 로직을 추가할 수 있음
  4. 요청 취소
    • CancelToken을 사용해 요청을 취소할 수 있음
  5. 타임아웃 설정
    • 요청 타임아웃을 설정할 수 있어, 너무 오래 기다리지 않도록 제어 가능함

:two: axios 설치 방법

npm install axios # npm 
yarn add axios # yarn

:three: HTTP 메서드 사용법

Axios는 다양한 HTTP 메서드를 지원함. 주로 사용하는 메서드는 GET, POST, PUT, DELTE, PATCH가 있음

:pushpin: 3-1) GET 요청

GET메서드는 서버에서 데이터를 가져오는 데 사용하며 주로 데이터 조회 할 때 사용함

axios.get("/posts")
  .then((response) => console.log(response.data))
  .catch((error) => console.error(error));

// 비동기 처리
const fetchData = async () => {
  try{
    const response = await axios.get("/posts");
    // data만 필요할 경우 구조 분해 할당(디스트럭처링)으로 처리해도 됌
    // const { data } = await axios.get("/posts/");
    console.log(response.data);    
  }catch(e){
    console.log("error =>", e);
  }
}

:pushpin: 3-2) POST 요청

POST메서드는 서버에 데이터를 전송하거나 새로운 데이터를 생성하는 데 사용함.

export const handleUserLogin = async (userData) => {
  const response = await USER_API.post("/login", userData);
  return response.data;
};

export const createTestResult = async (resultData) => {
  await MBTI_API.post("/mbti", resultData)
};

:pushpin: 3-3) PUT 요청

PUT 메서드는 서버에 있는 데이터를 완전히 교체할 때 사용함. (덮어쓰기임)

axios.put("/posts/1", { title: '변경 타이틀', content: '변경 내용' })
  .then((response) => {
    console.log('Post replaced:', response.data);
  })
  .catch((error) => {
    console.error('axios put error', error);
  });

:pushpin: 3-4) DELETE 요청

DELETE 메서드는 서버에서 데이터를 삭제할 때 사용함.

export const deleteTestResult = async (id) => {
  await MBTI_API.delete(`/mbti/${id}`)
};

:pushpin: 3-4) PATCH 요청

PATCH 메서드는 서버에 있는 데이터를 부분적으로 수정할 때 사용함. (부분 업데이트임)

export const updateTestResultVisibility = async ({id, vis}) => {
  console.log("visibility=>", vis);
  await MBTI_API.patch(`/mbti/${id}`, {visibility: !vis})
};

:four: Axios의 Custom Instance 사용법

:pushpin: 4-1) Custom Instance 란?

커스텀 인스턴스는 여러 API 요청에서 동일한 설정을 재사용할 수 있게 해줌.

  • Base URL, Headers 같은 공통 설정을 하나의 인스턴스에 정해두면 각 요청마다 반복새허 설정할 필요가 없음
  • 프로젝트가 엄청 커서 axios를 1000번 사용한다 했을 때와 특히 갑자기 base URL이 변경되었을 때 생각해보면 됌 (1000번 일일이 수정해줄거냐 vs 한 곳에서 관리할꺼냐)

:pushpin: 4-2) Custom Instance 적용

axios.create의 입력값으로 들어가는 객체는 configuration 객체이며 자세한 내용은 공식 문서를 참고!

// Custom Instance 만들기
// src/instance/baseInstance.js
import axios from 'axios';

export const USER_API = axios.create({
  baseURL: "http://localhost:4000"
})

// App.jsx
import "./App.css";
import { useEffect } from "react";
import api from "./axios/api";

function App() {
  useEffect(() => {
    api
      .get("/user")
      .then((res) => {
        console.log("결과 => ", res.data);
      })
      .catch((err) => {
        console.log("오류가 발생하였습니다!");
      });
  }, []);

  return <div>axios 예제입니다.</div>;
}

export default App;

:five: Axios의 Interceptors 사용법

:pushpin: 5-1) Interceptors란?

axios interceptors[출처 : https://javascript.plainenglish.io/how-to-implement-a-request-interceptor-like-axios-896a1431304a]

인터셉터는 요청 또는 응답을 쌔벼서(가로채서), 추가 로직을 삽입할 수 있게 도와줌

  • API 요청 전이나 응답을 받기 전/후에 특정 작업 수행이 가능함
  • 예를 들어, 토큰 인증을 요청 헤더에 자동으로 추가 하거나, 에러 처리 로직을 응답 시 적용 가능
    • 요청 헤더 추가
    • 인증 관리
    • 로그 관련 로직 삽입
    • 에러 핸들링

:pushpin: 5-2) Interceptor 적용

요청을 보낼 때와 응답을 받을 때 특정 작업을 수행하려면 아래와 같이 적용하면 됨

import axios from "axios";

const instance = axios.create({
  baseURL: "http://localhost:4000",
});

instance.interceptors.request.use(
  function (config) {
    // 요청을 보내기 전 수행
    console.log("인터셉트 요청 성공!");
    return config;
  },
  function (error) {
    // 오류 요청을 보내기 전 수행
    console.log("인터셉트 요청 오류!");
    return Promise.reject(error);
  }
);

instance.interceptors.response.use(
  function (response) {
    console.log("인터셉트 응답 받았어요!");
    // 정상 응답
    return response;
  },
  function (error) {
    console.log("인터셉트 응답 못받았어요...ㅠㅠ");
    return Promise.reject(error);
  }
);

export default instance;

:pushpin: 5-3) 사용 예시 - 토큰/에러

Interceptor의 역할에 대해 간략한 설명을 추가하는 것이 좋다.

  • 인텁세터는 Axios요청 또는 응답 전후에 특정 작업을 수행하며 이번 개인과제에서 겪었던 인증 토큰 추가나 오류 처리에도 유용하게 적용할 수 있을 것 같다.
// 토큰 처리 예시
instance.interceptors.request.use(
  function (config) {
    // 요청을 보내기 전 토큰을 헤더에 추가
    const token = localStorage.getItem("token");
    if (token) {
      config.headers.Authorization = `Bearer ${token}`;
    }
    console.log("인터셉트 요청 성공!");
    return config;
  },
  function (error) {
    console.log("인터셉트 요청 오류!");
    return Promise.reject(error);
  }
);

// 에러 처리 개선
instance.interceptors.response.use(
  function (response) {
    console.log("인터셉트 응답 받았어요!");
    return response;
  },
  function (error) {
    if (error.response) {
      switch (error.response.status) {
        case 401:
          console.log('인증되지 않았습니다! 로그인으로 리디렉션 중...');
          // 로그인 페이지로 리디렉션
          localStorage.removeItem('token');
          window.location.href = '/login';
          break;
        case 404:
          console.log('리소스를 찾을 수 없습니다');
          break;
        case 500:
          console.log('서버오류');
          break;
        default:
          console.log('오류가 발생함!');
      }
    } else {
      // 응답이 없을 경우 네트워크 문제일 가능성
      console.log("네트워크 오류 또는 서버가 응답하지 않습니다.");
    }
    return Promise.reject(error);
  }
);

:pushpin: 5-4) 인스턴스 + 인터셉터 활용

  • apiClient.js
import axios from 'axios';

const apiClient = axios.create({
  baseURL: 'https://api.example.com',
  timeout: 1000,
});

// 요청 인터셉터, 응답 인터셉터 설정
apiClient.interceptors.request.use(/* ... */);
apiClient.interceptors.response.use(/* ... */);

export default apiClient;
  • userApi.js
import apiClient from './apiClient';

// 사용자 관련 API 요청
export const getUserProfile = () => apiClient.get('/user/profile');
export const updateUserProfile = (data) => apiClient.patch('/user/profile', data);
  • authApi.js
import apiClient from './apiClient';

// 인증 관련 API 요청
export const login = (credentials) => apiClient.post('/auth/login', credentials);
export const logout = () => apiClient.post('/auth/logout');
  • App.jsx
import { getUserProfile, updateUserProfile } from './api/userApi';
import { login, logout } from './api/authApi';

// 사용자 프로필 가져오기
getUserProfile().then(response => console.log(response.data));

// 사용자 프로필 업데이트
updateUserProfile({ name: 'New Name' }).then(response => console.log(response.data));

// 로그인
login({ username: 'user', password: 'pass' }).then(response => console.log(response.data));

// 로그아웃
logout().then(response => console.log(response.data));

:fire: 마무리

  • Axios에서 제공하는 Interceptor 기능을 통해 요청 전/후에 특정 작업을 쉽게 추가할 수 있다.
  • 매번 API 요청 시 JWT 토큰을 자동으로 추가하거나 응답 에러를 일관성 있게 처리할 수 있다.
  • 이렇게 작성된 인터셉터는 모든 API 요청에 적용되어 코드의 중복을 줄이고, 오류를 효과적으로 관리할 수 있도록 도와줌.

태그:

카테고리: ,

업데이트: