API 요청시 토큰 만료로 인한 401 에러가 발생할 경우를 대응하기 용도입니다.
graph LR
A[API 요청] --> B{401 에러 발생?}
B -- 아니오 --> Z[정상 응답]
B -- 예 --> C[실패한 API 대기 큐에 저장]
C --> D{refreshToken 재발급 중?}
D -- 아니오 --> E[refreshToken으로 토큰 재발급 요청]
E --> F{재발급 성공?}
F -- 예 --> G[대기 큐의 모든 API 재요청]
G --> H{재요청 성공?}
H -- 예 --> Z
H -- 아니오 --> I[에러 반환]
F -- 아니오 --> I
D -- 예 --> J[대기 큐에 계속 저장]
J --> E
api.interceptors.response.use(
(response) => response, // 정상 응답은 그대로
async (error) => {
// 401 에러 시 토큰 재발급 로직
const originalRequest = error.config;
if (
error.response &&
error.response.status === 401 &&
!originalRequest._retry
) {
originalRequest._retry = true;
try {
// 토큰 재발급 요청
const res = await axios.post('/auth/refresh', {
refreshToken: localStorage.getItem('refreshToken'),
});
const newToken = res.data.accessToken;
localStorage.setItem('accessToken', newToken);
// 원래 요청에 새 토큰 적용
originalRequest.headers.Authorization = `Bearer ${newToken}`;
return api(originalRequest); // 재요청
} catch (refreshError) {
// 재발급 실패 시 처리 (예: 로그아웃)
return Promise.reject(refreshError);
}
}
// 기타 에러 처리
return Promise.reject(error);
}
);
[originalRequest._retry 용도]
“두 번째로 같은 요청이 실패" 하는 경우
토큰 재발급이 실패하거나 재발급된 토큰이 유효하지 않거나서버에서 refresh token도 만료된 상태라면 → 재요청(두 번째 요청)도 401 에러가 발생할 수 있습니다.
만약 _retry 플래그가 없다면, 401 → 재발급 → 재요청 → 또 401 → 또 재발급 흐름으로 무한 루프가 발생할 수 있습니다.
[재발급 완료 후 재요청 과정에서 헤더에 다시 토큰을 업데이트하는 이유]