Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 25x 25x 25x 25x 25x 25x 25x 25x 25x 25x 25x 25x 1x 1x 1x 18x 18x 1x 6x 6x 6x 6x 6x 6x 6x 6x 6x 6x 6x 1x 1x 1x 1x 1x 1x 18x 18x 13x 13x 13x 18x 18x 8x 2x 2x 18x 18x 18x 18x 1x 1x 1x 18x 18x 3x 2x 2x 18x 1x 1x 1x 1x | import axios from 'axios';
import { CommonErrorResponse, CommonSuccessResponse } from '@/types/service/common';
import { API } from '..';
export const baseAPI = axios.create({
baseURL: process.env.NEXT_PUBLIC_API_BASE_URL,
timeout: 20000,
});
baseAPI.interceptors.request.use(async (config) => {
const isServer = typeof window === 'undefined';
if (isServer) {
// // Server 환경
const { cookies } = await import('next/headers');
const cookieStore = await cookies();
const token = cookieStore.get('accessToken')?.value;
if (token && config.headers) {
config.headers.Authorization = `Bearer ${token}`;
}
} else {
// Client 환경
const match = document.cookie.match(new RegExp('(^| )accessToken=([^;]+)'));
const token = match ? decodeURIComponent(match[2]) : undefined;
if (token && config.headers) {
config.headers.Authorization = `Bearer ${token}`;
}
}
return config;
});
baseAPI.interceptors.response.use(
(response) => {
return response;
},
async (error) => {
const errorResponse: CommonErrorResponse = error.response?.data || {
type: 'about:blank',
title: 'Network Error',
status: 0,
detail: '서버와 연결할 수 없습니다.',
instance: error.config?.url || '',
errorCode: 'NETWORK_ERROR',
};
const status = error.response?.status ?? errorResponse.status;
const isServer = typeof window === 'undefined';
const originalRequest = error.config;
if (status === 401 && !originalRequest._retry) {
originalRequest._retry = true;
try {
await API.authService.refresh();
return baseAPI(originalRequest);
} catch (refreshError) {
if (isServer) {
const { redirect } = await import('next/navigation');
redirect('/login');
} else {
if (window.location.pathname === '/login') {
throw errorResponse;
}
const currentPath = window.location.pathname + window.location.search;
window.location.href = `/login?error=unauthorized&path=${encodeURIComponent(currentPath)}`;
}
throw refreshError;
}
}
if (status === 404) {
if (isServer) {
const { notFound } = await import('next/navigation');
notFound();
}
}
throw errorResponse;
},
);
type ApiVersionType = 'v1' | 'v2';
// 공통 응답 형식 처리를 위한 api 헬퍼
const apiHelper = (v: ApiVersionType = 'v1') => ({
// eslint-disable-next-line @typescript-eslint/no-explicit-any
get: async <T>(url: string, config?: any): Promise<T> => {
const response = await baseAPI.get<CommonSuccessResponse<T>>(`/api/${v}${url}`, config);
return response.data.data;
},
// eslint-disable-next-line @typescript-eslint/no-explicit-any
post: async <T>(url: string, data?: any, config?: any): Promise<T> => {
const response = await baseAPI.post<CommonSuccessResponse<T>>(`/api/${v}${url}`, data, config);
return response.data.data;
},
// eslint-disable-next-line @typescript-eslint/no-explicit-any
put: async <T>(url: string, data?: any, config?: any): Promise<T> => {
const response = await baseAPI.put<CommonSuccessResponse<T>>(`/api/${v}${url}`, data, config);
return response.data.data;
},
// eslint-disable-next-line @typescript-eslint/no-explicit-any
delete: async <T>(url: string, config?: any): Promise<T> => {
const response = await baseAPI.delete<CommonSuccessResponse<T>>(`/api/${v}${url}`, config);
return response.data.data;
},
// eslint-disable-next-line @typescript-eslint/no-explicit-any
patch: async <T>(url: string, data?: any, config?: any): Promise<T> => {
const response = await baseAPI.patch<CommonSuccessResponse<T>>(`/api/${v}${url}`, data, config);
return response.data.data;
},
});
export const api = apiHelper('v1'); // breaking change 방지용
export const apiV1 = apiHelper('v1');
export const apiV2 = apiHelper('v2');
|