항해 16기/Today I Learned

[항해 30일차] TIL_React 심화주차: axios 심화 - instance & interceptor

해갈 2023. 9. 7. 15:22

학습 목표

  1. axios interceptor 픠 필요성에 대해 배우고, interceptor 를 이해하기 위한 필수 개념인 instance 도 함께 이해합니다.
  2. 여러 예시를 실제로 사용해보며, 사용방법을 체득합니다.

 

axios interceptor 의 개념과 필요성

상황을 통해 살펴보는 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개 정도 존재한다고 가정해보겠습니다. 며칠 후, 어떠한 이유 때문에 호출하는 서버가 변경되었습니다.

  • 변경 전 : http://localhost:3001
  • 변경 후 : http://localhost:4000

그렇다면, 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]

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

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

이러한 부분에서 빛을 발합니다.

 

실습

instance 만들기, baseURL 설정하기

지금까지 

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

위와 같은 방법으로 데이터 통신을 해왔습니다. axios 를 썼죠. 완전히 plain axios, 순수 axios 입니다. custom 설정이 전혀 되어있지 않았죠. 이 axios 를 인스턴스(instance) 라고 합니다.

우선, json-server 를 설정해준 뒤,

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 파일만 수정해주면 되는거죠.

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;

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

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

 

실패 지켜보기

이번에는 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 이기 때문에 짧은 시간이어서 서버에서 응답을 받기 전에 오류를 내게 될 겁니다.

예상한 대로, 요청은 성공했지만, 응답을 못받았습니다.