[유데미x스나이퍼팩토리] 10주 완성 프로젝트 캠프 - Axios interceptor

강경서·2023년 8월 17일
0
post-thumbnail

🧲 Axios interceptor

Axios는 node.js와 브라우저를 위한 Promise 기반 HTTP 클라이언트 입니다. 저희 프로젝트는 Fetch API를 사용하여 HTTP 통신을 진행하고 있지만 JWT를 사용하여 인증체계를 형성하보니 새로운 토큰을 받는데 조금 불편한점이 있어 Axios interceptor를 사용하기로 했습니다.


Axios interceptor

Axios interceptor는 then 또는 catch로 처리되기 전에 요청과 응답을 가로챌수 있습니다.
이를 이용하여 새로운 Access Token을 갱신할때 효율적으로 처리할 수 있습니다.

// 요청 인터셉터 추가하기
axios.interceptors.request.use(function (config) {
    // 요청이 전달되기 전에 작업 수행
    return config;
  }, function (error) {
    // 요청 오류가 있는 작업 수행
    return Promise.reject(error);
  });

// 응답 인터셉터 추가하기
axios.interceptors.response.use(function (response) {
    // 2xx 범위에 있는 상태 코드는 이 함수를 트리거 합니다.
    // 응답 데이터가 있는 작업 수행
    return response;
  }, function (error) {
    // 2xx 외의 범위에 있는 상태 코드는 이 함수를 트리거 합니다.
    // 응답 오류가 있는 작업 수행
    return Promise.reject(error);
  });

Axios interceptor 적용하기

import axios from "axios";

// axios interceptors를 이용하여 token을 관리합니다.
const useApi = () => {
  // axios 인스턴스를 생성합니다.
  const api = axios.create({ headers: { Accept: "application/json" } });
  // 요청 인터셉터를 추가합니다.
  api.interceptors.request.use((config) => {
    const localAccessToken = localStorage.getItem(ACCESS_TOKEN);
    const parsedAccessToken = localAccessToken && JSON.parse(localAccessToken);
    if (parsedAccessToken) {
      config.headers.Authorization = `Bearer ${parsedAccessToken.token}`;
    }
    return config;
  });
// ...
  return { api };
};

요청 인터셉터에는 LocalStorage에서 가져온 AccessToken을 HTTP Header에 넣어주는 역할을 합니다.

// 새로운 토큰을 받아오는 함수입니다.
const getToken = async () => {
    const localRefreshToken = localStorage.getItem(REFRESH_TOKEN);
    const parsedRefreshToken =
      localRefreshToken && JSON.parse(localRefreshToken);
    const { handleAccessToken, handleRefreshToken } = useTokenControl();
    const {
      data: { accessToken, refreshToken },
    } = await axios({
      method: "POST",
      url: "http://223.130.161.221/mapi/v1/tokens",
      headers: {
        Accept: "application/json",
        Authorization: `Bearer ${parsedRefreshToken.token}`,
      },
    });
    // 토큰을 로컬스토리지에 저장합니다.
    handleAccessToken(accessToken);
    handleRefreshToken(refreshToken);
    return accessToken;
  };

해당 함수는 새로운 Token을 받아오는 함수입니다. useTokenControl이란 Token을 LocalStorage에 저장하는 커스텀 훅을 불러와 Token을 저장시켜줍니다. 새로운 AccessToken은return시켜 직접 사용할 수 있도록 만들었습니다.

// 응답 인터셉터를 추가합니다.
api.interceptors.response.use(
  (response) => {
    return response;
  },
  async (error) => {
    const {
      config,
      response: { status },
    } = error;
    if (status !== 401 || config.sent) {
      return Promise.reject(error);
    }
    config.sent = true;
    const { accessToken } = await getToken();
    if (accessToken) {
      config.headers.Authorization = `Bearer ${accessToken}`;
    }
    return api(config);
  }
);

응답 인터셉터는 response의 status가 401일때 새로운 Token을 받아오는 getToken을 실행합니다. 이는 Token의 유효기간이 만효될시 401 status를 반환하기 때문입니다. 그 후 HTTP Header에 새로운 Access Token을 담아 다시 통신을 시도합니다.

config.sent를 true로 지정함으로써 refresh 요청이 끝나고 재요청을 보냈는데도 에러가 발생한 경우 재귀적으로 loop가 발생을 방지시켜줍니다.


🧾 Reference



본 후기는 유데미-스나이퍼팩토리 10주 완성 프로젝트캠프 학습 일지 후기로 작성 되었습니다.

#프로젝트캠프 #프로젝트캠프후기 #유데미 #스나이퍼팩토리 #웅진씽크빅 #인사이드아웃 #IT개발캠프 #개발자부트캠프 #리액트 #react #부트캠프 #리액트캠프

profile
기록하고 배우고 시도하고

0개의 댓글