Axios Interceptor로 Access token/Refresh token 처리하기

sukjune96·2023년 11월 29일
2

React

목록 보기
3/3
post-thumbnail

문제상황

프로젝트에서 로그인 기능처럼 AccessToken이 필요없는 요청을 제외하고 대부분의 요청에 대해 AccessToken을 Header에 담아 보내야했다. 이를 위해 axiosInstance를 따로 만들어서 사용하는 방법을 사용했었다.

const 토큰넣은Instance = axios.create({
  baseURL: process.env.SERVER_URL,
  headers: {
    'Content-Type': 'application/json',
    Authorization: `Bearer ${getToken('accessToken')}`,
  },
});

const 토큰없는Instance = axios.create({
  baseURL: process.env.SERVER_URL,
  headers: {
    'Content-Type': 'application/json',
  },
});

위 코드처럼 인스턴스를 하나 더 만들었고, 토큰에 대한 수정 사항이 생기면 인스턴스를 갈아끼우는 불편한 경험을 했다. 이를 해결하기 위해 Interceptor를 활용해 서버로 가는 요청에 토큰을 넣어주는 방식으로 수정했다.


Interceptor의 역할

인터셉터는 클라이언트와 서버 사이에서 요청을 가로채서 중간에 처리를 하는 역할을 한다.

request와 response 두 상황 모두 적용할 수 있으며 구성은 아래와 같다.

axios.interceptors.request.use(
  function (config) {
    // 요청을 보내기 전에 수행할 작업
    return config;
  },
  function (error) {
    // 요청을 보내기 전 에러가 발생했을 때 수행할 작업
    return Promise.reject(error);
  }
);

Interceptor를 활용해 Access token 추가하기

1. 우선 기존과 동일한 axios Instance를 만들어준다.

const axiosInstance = axios.create({
	baseURL: process.env.SERVER_URL
});

2. 그 다음 로컬스토리지에 저장되어 있는 accessToken을 Header에 담아주는 addAccessToken함수를 만들어준다.

// config는 request보내기 전 수정가능한 객체
const addAccessToken = (config) => {
  const accessToken = localStorage.getItem('AccessToken');
  if (accessToken) {
    config.headers.Authorization = `Bearer ${accessToken}`;
  }
  return config;
};

3. 생성한 interceptor를 axios Instance에 할당해준다.

axiosInstance.interceptors.request.use(addAccessToken, (err) => {
  return Promise.reject(err);
});

이렇게 인터셉터를 통해 API 요청이 서버로 도달하기 전에 요청을 가로채 특정 요구사항을 처리할 수 있다.

Interceptor를 활용해 token 갱신하기

현재 프로젝트의 서버에서는 Access token이 만료되면 401에러를 리턴해준다. 만약 Access token이 만료되어 refresh token으로 갱신해줘야하는 상황이라면, response에 대한 Interceptor로 에러발생 시 갱신 요청을 수행할 수 있다.

const handleRefreshToken = async (error) => {
  if (!error.response || error.response.status !== 401) return Promise.reject(error);
  
  const originalRequest = error.config;
  
  try {
    // 토큰 갱신 요청 보내기
    const newTokens = await refreshAccessToken();

    // 갱신받은 access 토큰 저장
    localStorage.setItem('Authorization', newTokens.Authorization);

    // 새 토큰으로 헤더 수정
    originalRequest.headers.Authorization = `Bearer ${newTokens.Authorization}`;

    // 재요청
    return axiosInstance(originalRequest);
  } catch (refreshError) {
    alert('인증이 만료되었습니다. 다시 로그인해주세요');
 	// 로그인 페이지로 이동
    return Promise.reject(refreshError);
  }
};


axiosInstance.interceptors.response.use((response) => response, handelRefreshToken);

간략하게 표현하면 위 코드 순서대로 동작하게 된다.

  1. 401 Unauthorized 발생
  2. refresh token으로 새로운 access token 발급 요청 (refreshAccessToken 함수)
  3. 성공 시 access token 저장
  4. 원래 요청(originalRequest)에 새 access token을 넣고 재전송
profile

0개의 댓글