Skip to content

Commit

Permalink
refactor : service api.ts
Browse files Browse the repository at this point in the history
  • Loading branch information
cmlim0070 committed Jan 16, 2025
1 parent 1628c21 commit d8d0891
Showing 1 changed file with 71 additions and 54 deletions.
125 changes: 71 additions & 54 deletions src/service/api.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,30 @@
import axios, { AxiosRequestConfig, AxiosInstance } from 'axios';
import axios, { AxiosRequestConfig, AxiosInstance, AxiosError } from 'axios';
import { tokenStorage } from './auth/tokenStorage';
import { refreshAccessToken } from '@/service/auth/refreshAccessToken';
import { logout } from './auth/logout';
import { formatApiError } from '@/util/formatApiError';

interface QueueItem {
resolve: (token: string) => void;
reject: (error: QueueError) => void;
}

type QueueError = AxiosError | Error;

const baseUrl = import.meta.env.VITE_API_URL as string;

let isRefreshing = false;
let refreshSubscribers: ((token: string) => void)[] = [];

// TODO - λŒ€κΈ°μ€‘μΈ μš”μ²­ 처리 ν•¨μˆ˜ κ΅¬ν˜„
// . . .
let requestQueue: QueueItem[] = [];
const processQueue = (error: QueueError | null, token: string | null): void => {
requestQueue.forEach((promise: QueueItem) => {
if (error) {
promise.reject(error);
} else if (token) {
promise.resolve(token);
}
});
requestQueue = [];
};

export const defaultApi = (option?: AxiosRequestConfig): AxiosInstance => {
const instance = axios.create({
Expand All @@ -19,6 +33,7 @@ export const defaultApi = (option?: AxiosRequestConfig): AxiosInstance => {
...option
});

// μš”μ²­ 인터셉터
instance.interceptors.request.use(
function (config) {
const accessToken = tokenStorage.getAccessToken();
Expand All @@ -32,65 +47,58 @@ export const defaultApi = (option?: AxiosRequestConfig): AxiosInstance => {
}
);

// μ•‘μ„ΈμŠ€ 토큰 만료됨
// 응닡 인터셉터
instance.interceptors.response.use(
function (response) {
return response;
},
async function (error) {
console.error('μ—λŸ¬:', error);

const originalRequest = error.config;

if (error.response?.status === 401 && !originalRequest._retry) {
if (!isRefreshing) {
isRefreshing = true;
originalRequest._retry = true;
// κ°±μ‹  쀑
if (isRefreshing) {
return new Promise((resolve, reject) => {
requestQueue.push({
resolve: (token: string) => {
originalRequest.headers['Authorization'] =
`Bearer ${token}`;
resolve(instance(originalRequest));
},
reject
});
});
}

try {
// μ•‘μ„ΈμŠ€ν† ν° μž¬λ°œκΈ‰ μ™„λ£Œ
const refreshAccessTokenResponse =
await refreshAccessToken();
isRefreshing = true;
originalRequest._retry = true;

if (refreshAccessTokenResponse.isSuccess) {
console.log('μ•‘μ„ΈμŠ€ 토큰 μž¬λ°œκΈ‰λ¨');
const newAccessToken =
refreshAccessTokenResponse.result
.newAccessToken;
console.log(newAccessToken);
tokenStorage.setAccessToken(newAccessToken);
try {
const response = await refreshAccessToken();

originalRequest.headers['Authorization'] =
`Bearer ${newAccessToken}`;
if (response.isSuccess && response.result.newAccessToken) {
const newAccessToken = response.result.newAccessToken;
tokenStorage.setAccessToken(newAccessToken);

// λŒ€κΈ° μš”μ²­μ— 토큰 전달
refreshSubscribers.forEach((callback) =>
callback(newAccessToken)
);
originalRequest.headers['Authorization'] =
`Bearer ${newAccessToken}`;

refreshSubscribers = [];
return instance(originalRequest);
}
// λ¦¬ν”„λ ˆμ‹œ 토큰 만료
logout();
window.location.href = '/login';
return Promise.reject(error);
} catch (error) {
// λ„€νŠΈμ›Œν¬ μ—λŸ¬?
return Promise.reject(error);
} finally {
isRefreshing = false;
processQueue(null, newAccessToken);
return instance(originalRequest);
}
logout();
window.location.href = '/login';
return Promise.reject(error);
} catch (error) {
processQueue(
new Error('둜그인 토큰이 λ§Œλ£Œλ˜μ—ˆμŠ΅λ‹ˆλ‹€.'),
null
);
logout();
window.location.href = '/login';
return Promise.reject(error);
} finally {
isRefreshing = false;
}

// λŒ€κΈ° μš”μ²­
return new Promise((resolve) => {
refreshSubscribers.push((token: string) => {
originalRequest.headers['Authorization'] =
`Bearer ${token}`;
resolve(instance(originalRequest));
});
});
}
return Promise.reject(error);
}
Expand All @@ -104,12 +112,21 @@ export const defaultApi = (option?: AxiosRequestConfig): AxiosInstance => {
return response;
},
(error) => {
console.error('μ—λŸ¬:', error);
if (error)
if (error.response?.data) {
throw formatApiError(
error.response.data.code,
error.response.data.message
);
} else if (!error.response) {
throw formatApiError(
'ERROR500',
'λ„€νŠΈμ›Œν¬ μš”μ²­μ— μ‹€νŒ¨ν–ˆμŠ΅λ‹ˆλ‹€.'
'NETWORK_ERROR',
'μ„œλ²„μ™€μ˜ 톡신에 μ‹€νŒ¨ν–ˆμŠ΅λ‹ˆλ‹€.'
);
}
throw formatApiError(
'UNKNOWN_ERROR',
'μš”μ²­ 처리 쀑 λ¬Έμ œκ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€.'
);
}
);

Expand Down

0 comments on commit d8d0891

Please sign in to comment.