내장함수 fetch의 단점
같은 요청에 대해서도 똑같은 URI를 복붙해서 사용하고 이는 백엔드 URI 변경 및 추가적인 변경에 대한 대처가 미흡하다.
이를 해결하려면? 서비스 레이어로 분리.
컴포넌트와 요청을 관리하는 fetch함수를 따로 분리하고. 커스텀을 위해 axios 라이브러리를 활용
axios인스턴스를 도입하면서 uri의 중복을 막고 유지보수성을 향상
class API {
readonly method: HTTPMethod;
readonly url: string;
baseURL?: string;
headers?: HTTPHeaders;
data?: unknown;
timeout?: number;
withCredentials?: boolean;
constructor(method: HTTPMethod, url: string) {
this.method = method;
this.url = url;
}
// withCridentials가 포함되면 인터셉터가 동작.
call<T>(): AxiosPromise<T> {
const http = axios.create();
if (this.withCredentials) {
// 인터셉터를 활용
http.interceptors.response.use(
(response) => response,
(error) => {
if (error.response && error.response.status === 401) {
//에러처리
}
return Promise.reject(error);
}
);
}
return http.request({ ...this });
}
}
class APIBuilder {
private _instance: API;
constructor(method: HTTPMethod, url: string, data?: unknown) {
this._instance = new API(method, url);
this._instance.baseURL = 'hostURL';
this._instance.data = data;
this._instance.headers = {
'Content-Type': 'application/json;charset=utf-8',
};
this._instance.timeout = 5000;
this._instance.withCredentials = false;
}
static get = (url: string) => new APIBuilder('GET', url);
static put = (url: string, data: unknown) => new APIBuilder('PUT', url, data);
static post = (url: string, data: unknown) =>
new APIBuilder('POST', url, data);
static delete = (url: string) => new APIBuilder('DELETE', url);
baseURL(value: string): APIBuilder {
this._instance.baseURL = value;
return this;
}
headers(value: HTTPHeaders): APIBuilder {
this._instance.headers = value;
return this;
}
//...
}
/// 사용 예ㅒ제
const fetchJobNameList = async(name:string, size?:number){
const api = APIBuilder.get("api/web/jobs")
.withcredentials(true)
.params({name, size})
.build()
const {data} = await api.call<Response<JobNameListResponse>>
return data
}
interface Response<T> {
data: T;
status: string;
serverDateTime: string;
errorCode?: string; //FAIL, ERROR
errorMessage?: string;
}
const fetchCart = (): AxiosPromise<Response<FetchCartResponse>> =>
apiRequester.get<Response<FetchCartResponse>>'cart';
UPDATE나 CREATE같이 응답이 없을 수 있는 API처리가 까다로워진다. 따라서 Response 타입은 apiRequester가 모르게 관리되어야 한다.