티스토리 뷰

TIL

axiosInstance 리펙토링하기

윤미주 2024. 7. 6. 01:53

📖 AxiosInstance 리펙토링이 필요한 이유

1. ` basicAxiosInstance `

기본 axiosInstance

 

2. ` axiosInstance `

accessToken을 헤더에 담고, accessToken이 만료된 경우 refreshToken을 이용해 accessToken 재발급요청을 해주는 axiosInstance 

 

2개의 instance를 만들어 사용하고 있는데 accessToken 재발급 요청해준는 부분만 따로 분리하여 사용해야하는 경우가 생겼다. 코드를 제대로 분리하기로 마음먹었다. 

 

사실 분리만 했기때문에 크게달라진것은 없으나, 리펙토링전 코드와 리펙토링 후 작성하게된 TIL이 있어서 작성이 필요했다..!!

 

그 경우를 알고 싶은 분은 아래 블로그 경로를 참고해주세요🤣

https://anywhereim.tistory.com/111

 

토큰 만료처리하기

프로젝트를 진행하면서 부족한 부분들이 생긴다.그래서 프로젝트를 하면서 중간중간 리펙토링도 많고 추가 해야하는 기능도 많아 두서없는 TIL을 쓰게 된다.. ㅎ쨋든. 📖AxiosInstance 이외에 토큰

anywhereim.tistory.com

 

 

❓ 리펙토링 된 부분

getNewAccessToken 

1. getNewAccessToken 함수에 별도 axiosInstance 생성.

2. `axios.defaults.withCredentials = true` 옵션으로 전역설정 

2. localstorage.remove 코드 삭제.

3. error 발생 시 loacalStorage에 담는 정보 전체 삭제 및 로그인 페이지로 리다이렉션 코드 포함.

 

axiosInstance 

1. error 발생 시 loacalStorage에 담는 정보 전체 삭제 및 로그인 페이지로 리다이렉션 코드 제거

 

basicAxiosInstance

1. ` axios.defaults.withCredentials = false ` 옵션으로 전역에서 ` withCredentials= true `설정으로 인해 api요청 시 보내는 불필요한 쿠키 보내지 않게하기

 

💎 리펙토링된 코드

리펙토링 전 코드가 궁금하신 분은 아래 블로그를 참고해주세요. 

https://anywhereim.tistory.com/95

 

axiosInstance 작성해보기(accessToken, refreshToken)

이전 내용에 이어서 axiosInstance코딩한 내용을 작성해보고자 한다. fetch보다 사용성도 좋고 error 핸들링이 좋은 axios 알랍유야.. ***sessionstorage에서 localstorage로 변경.💡먼저 axiosInstance를 작성하게

anywhereim.tistory.com

 

< axiosInstance >

import axios from "axios";
import { getNewAccessToken } from "./withCredentials";

const axiosInstance = axios.create({
  baseURL: process.env.NEXT_PUBLIC_BASE_URL,
  headers: {
    "Content-Type": "application/json",
  },
  responseType: "json",
  withCredentials: true,
});

// 요청 인터셉터 설정
axiosInstance.interceptors.request.use(
  (config) => {
    const token = localStorage.getItem("token");
    if (token) {
      config.headers["Authorization"] = `Bearer ${token}`;
    }
    return config;
  },
  (error) => {
    return Promise.reject(error.message);
  }
);

// 응답 인터셉터 설정
axiosInstance.interceptors.response.use(
  (response) => response,
  async (error) => {
    const originalRequest = error.config;

    //중복 요청 방지
    if (error.response.status === 401 && !originalRequest._retry) {
      originalRequest._retry = true;

      const newAccessToken = await getNewAccessToken();

      if (newAccessToken) {
        // 원래 요청의 헤더를 새로운 토큰으로 업데이트
        originalRequest.headers["Authorization"] = `Bearer ${newAccessToken}`;
        return axiosInstance(originalRequest);
      }
    }
    return Promise.reject(error);
  }
);

export default axiosInstance;

 

 

 

< getNewAccessToken >

import { decodeTokenOnServer } from "./decode/decodedAxios";
import { requests } from "./request";
import axios from "axios";

axios.defaults.withCredentials = true;

const axiosInstance = axios.create({
  baseURL: process.env.NEXT_PUBLIC_BASE_URL,
  headers: {
    "Content-Type": "application/json",
  },
  responseType: "json",
  withCredentials: true,
});

export const getNewAccessToken = async () => {
  try {
    console.log(
      "withCredentials 설정:",
      axiosInstance.defaults.withCredentials
    );

    const response = await axiosInstance.post(
      `${requests.getNewAccessToken}`,
      {},
      {
        withCredentials: true,
      }
    );
    const newAccessToken = response.data.data.accessToken;

    await decodeTokenOnServer(newAccessToken);

    localStorage.setItem("token", newAccessToken);
    return newAccessToken;
  } catch (error: any) {
    alert("로그인 정보가 만료되어 로그인이 필요합니다.");
    localStorage.removeItem("token");
    localStorage.removeItem("user");
    window.location.href = "/users/login";
    return null;
  }
};

 

 

< basicAxiosInstace >

import axios from "axios";

const basicAxiosInstance = axios.create({
  baseURL: process.env.NEXT_PUBLIC_BASE_URL,
  headers: {
    "Content-Type": "application/json",
  },
  responseType: "json",
  withCredentials: false,
});

export default basicAxiosInstance;