코딩/React

axios 심화 - instance와 interceptor

junhub 2023. 4. 28. 18:39

# axios interceptor의 개념과 필요성

 

(1) 상황을 통해 살펴보는 interceptor의 필요성

앞선 글에서 get, post, delete 등 axios를 활용하여 HTTP 통신을 하는 방법을 다뤘다. 

axios.get("http://localhost:3001/todos");
axios.post("http://localhost:3001/todos", todo);
axios.delete(`http://localhost:3001/todos/${todoId}`);

이렇게 호출하는 부분이 우리의 리액트 앱에 300개 정도 존재한다고 가정해보자.

그런데, 며칠 후 어떠한 이유 때문에 호출하는 서버가 변경되었다. 

 

그러면 우리는 300군데를 모두 찾아서 변경해줘야 한다. 엄청난 인적 리소스 낭비이다.

 

또한, 매번 요청을 할 때마다 console.log를 통해서 어떤 로깅을 하려 한다면, 300 곳을 찾아서 

console.log('요청 시작합니다...!');

코드를 넣어줘야 한다. 이 또한 엄청난 인적 리소스 낭비라고 볼 수 있다. 

 

axios interceptor는 이름에서 알 수 있듯, 다음 두 상황에서 흐름을 가로채서 여러분이 어떠한 코드 상의 관여를 할 수 있게 한다.

(1) 요청(request)이 처리되기 전( = http request가 서버에 전달되기 전)
(2) 응답(response)의 then(=성공) 또는 catch(=실패)가 처리되기 전

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

따라서, 위에서 가정했던 상황들을 포함하여 요청 및 응답시에 필요한 작업들을 한꺼번에 처리를 할 수 있다. 

  • 요청 헤더 추가
  • 인증 관리
  • 로그 관련 로직 삽입
  • 에러 핸들링

이러한 부분에서 빛을 발하게 된다. 

 

 

# 실습

 

(1) instance 만들기, baseURL 설정하기

const data = axios.get("http://localhost:4000/");

지금까지 위와 같은 방법으로 데이터 통신을 해왔었다. axios를 썼었다. 완전히 plain axios, 순수 axios이다.

custom 설정이 전혀 되어있지 않았다. 이 axios를 인스턴스(instance)라고 합니다. 

 

 

 

src > axios > api.js

import axios from "axios";

// axios.create의 입력값으로 들어가는 객체는 configuration 객체에요.
// https://axios-http.com/docs/req_config
// 위 주소를 참고해주세요!
const instance = axios.create({
	baseURL: "http://localhost:4000",
});

export default instance;

 

 

App.jsx

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

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

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

export default App;

자, get 요청하는 부분이 상당히 간결해졌다. 이제는 서버의 정보가

이렇게 변경이 되어도, api.js 파일만 수정해주면 된다. 

 

 

 

(2) request, response에 적용해보기

요청을 보낼 때, 그리고 서버로부터 응답을 받을 때(실패할 때) 특정한 일을 수행해야 한다면 어떻게 하면 될까? 다음 코드를 적용해보자.

 

 

src > axios > api.js

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;

 

 

브라우저에서 로그를 확인해보면

요청과 응답 중간에 가로채서 어떠한 작업을 수행해 주는 것을 볼 수 있다. 

 

 

 

(3) 실패 시켜보기

이번에는 instance의 설정을 변경시켜서 요청을 실패시켜보자.

import axios from "axios";

// axios.create의 입력값으로 들어가는 객체는 configuration 객체에요.
// https://axios-http.com/docs/req_config
// 위 주소를 참고해주세요!
const instance = axios.create({
	baseURL: "http://localhost:4000",
	timeout: 1,
});

export default instance;

이렇게 변경해주게 되면, 요청 타임아웃이 1ms(1 밀리세컨)

말도 안되는 짧은 시간이기 때문에 서버에서 응답을 받기 전에 오류를 내게 될 것이다. 

요청은 성공했지만, 응답을 못받았다. 응답에 대한 로그를 살펴보면, 아래와 같다. 

타임아웃 ‘1ms’을 초과하였습니다.

 

 

 

 

# 더 적용할 수 있는 부분

  • 요청 시, content-type 적용
  • token 등 인증 관련 로직 적용
  • 서버 응답 코드에 대한 오류 처리(controller)
  • 통신시작 및 종료에 대한 전역 상태를 관리하여 spinner, progress bar 등 구현 가능

사실, axios interceptor를 통해 통신의 중간과정에서 개발자의 머릿속에 있는 모든 것을 다 구현할 수 있다.