하루살이 개발일지

Axios : instance와 interceptor 본문

웹개발/React

Axios : instance와 interceptor

harusari 2023. 7. 4. 11:02

axios instance

axios instance는 HTTP 요청 설정을 미리 정의하여 재사용할 수 있도록 만든 객체이다.

생성하려면 axios.create 메서드를 사용한다.

const instance = axios.create({
    baseURL: '<https://api.example.com>',
    timeout: 1000,
    headers: {'X-Custom-Header': 'foobar'}
});
  • baseURL : 모든 요청에 대해 기본으로 사용할 url
  • timeout : 요청이 중단되기 전 대기할 시간 (밀리초 단위)
  • headers : 모든 요청에 공통으로 사용할 HTTP 헤더

 

요청 및 응답 처리

인스턴스를 통해 요청을 보낼 때 기본 설정이 자동으로 적용된다. 인스턴스에 일반 axios 메서드 (get, post, put, delete) 를 그대로 사용한다.

instance.get('/path/to/resource')
    .then(response => {
        console.log(response.data);
    })
    .catch(error => {
        console.error(error);
    });

 

실습

const data = axios.get("<http://localhost:3001/>");
  • 이런 방식은 plain axios 방식은 custom 설정이 전혀 되어있지 않음

.env

REACT_APP_SERVER_URL =http://localhost:3001
  • baseURL을 .env에 추가해주자

 

src > axios > api.js

import axios from "axios";

// axios instance 가공
export const apiClient = axios.create({
  baseURL: `${process.env.REACT_APP_SERVER_URL}`,
});

 

추가한 env를 instance의 baseURL에 넣어준다.

timeout과 headers는 따로 설정하지 않도록 하였다.

 

App.jsx

[변경 전]

const fetchTodos = async () => {
    const response = await axios.get(
      `${process.env.REACT_APP_SERVER_URL}/todos`
    );
    console.log(response.data);
    setTodos(response.data);
  };

 

[변경 후]

const fetchTodos = async () => {
    const response = await apiClient.get("/todos");
    console.log(response.data);
    setTodos(response.data);
  };

 

💡 바뀐 부분

  1. axios → apiClient로 axios instance를 사용하였다.
  2. baseURL이 있기 때문에 baseURL부분을 제외한 ‘/todos’ 라고만 전달해도 된다. 훨씬 간편해졌다.

 

timeout을 사용해 강제로 오류 발생시켜보기

  • timeout
    • 언제까지 기다릴거야! 그때까지 안오면 오류를 내버릴 거야!
    • 단위 : ms
export const apiClient = axios.create({
  baseURL: `${process.env.REACT_APP_SERVER_URL}`,
  timeout: 1,
});
  • 0.001초기 때문에 무조건 오류 남

 

 


axios interceptor

axios interceptor의 필요성

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

 

이 부분이 300군데 있고, 호출하는 서버가 바뀐다면?

또는, 매번 요청할 때마다 console.log를 추가하려고 하는 경우, 추가해야할 부분이 300군데 있다면?

 


axios interceptor의 개념

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

 

  • axios interceptor는 다음 두 상황에서 흐름을 가로채서 어떠한 코드 상의 관여를 할 수 있게 함
    • (1) 요청(request)이 처리되기 전( = http request가 서버에 전달되기 전)
    • (2) 응답(response)의 then(=성공) 또는 catch(=실패)가 처리되기 전
  • 따라서, 위에서 가정했던 상황을 포함해 요청 및 응답시에 필요한 작업들을 한꺼번에 처리할 수 있음
    • 요청 헤더 추가
    • 인증 관리
    • 로그 관련 로직 삽입
    • 에러 핸들링
    • 등등..

request, response 중간에 인터셉트

src > axios > api.js

import axios from "axios";

// axios instance 생성
export const apiClient = axios.create({
  baseURL: `${process.env.REACT_APP_SERVER_URL}`,
});

apiClient.interceptors.request.use(
  (config) => {
    // 요청을 보내기 전에 수행되는 함수
    console.log("인터셉트 요청 성공!");
    return config;
  },
  (error) => {
    // 요청에 실패했을 때 수행되는 함수 (오류 요청을 보내기 전)
    console.log("인터셉트 요청 오류!");
    return Promise.reject(error);
  }
);

apiClient.interceptors.response.use(
  (response) => {
    // 응답을 받았을 때 수행되는 함수 (응답을 내보내기 전)
    console.log("인터셉트 응답 받음!");
    return response;
  },
  (error) => {
    // 응답이 실패했을 때 수행되는 함수 (오류응답을 내보내기 전)
    console.log("인터셉트 응답 오류 발생!");
    return Promise.reject(error);
  }
);
  • 요청과 응답 중간에 가로채서 어떠한 작업들을 수행해 줌