에러 핸들링을 위임하는 fetch util 함수

fgStudy·2023년 2월 15일
1

프론트엔드 공부

목록 보기
6/6
post-thumbnail

기존 코드의 문제점

면접에서 라이브 코딩테스트로 기존에 내가 짠 코드를 리팩터링한 경험이 있다.
당시 제대로 답변을 못 했으나, 이번에 면접관분들께서 주신 피드백들을 토대로 리팩터링을 해보았다.

기존 fetch util함수는 파싱한 JSON 데이터를 반환하는 역할을 했다.

const fetchRequest = <T>(url: string, options?: RequestInit): Promise<T> {
  return fetch(url, options)
    .then(response => {
      if (!response.ok) {
        throw new Error(response.statusText);
      }
      return response.json() as Promise<T>;
    });
}

하지만 위의 코드에 대해 아래의 두 가지 보완점이 필요하다는 피드백들을 들었다.

  1. 각 상태코드에 따라 에러 핸들링을 fetch util에서 위임하게끔 구현하고 싶다.
    EX. HTTP 상태 코드가 401일 시 Redirect 작업을 fetch util에 위임한다.

  2. Response Data type은 JSON 이외에도 XML, HTML 등등 여러 가지가 존재한다.


리팩터링한 코드

const defaultJSONHeaders = {
  Accept: 'application/json',
};

const defaultHTMLHeaders = {
  Accept: 'text/html',
};

const parseJson = <T>(response: Response): Promise<T> => response.json();
const parseHtml = (response: Response) => response.text();

const request = async (url: string, fetchParams: FetchParams): Promise<Response> => {
  const newFetchParams = {
    ...fetchParams,
    method: fetchParams?.method?.toUpperCase() ?? 'GET',
    headers: {
      ...(fetchParams?.headers ?? {}),
      ...defaultJSONHeaders,
    },
    body: fetchParams?.body ? JSON.stringify(fetchParams.body) : undefined,
  };

  const response = await fetch(url, newFetchParams);
  if (response.ok) {
    return Promise.resolve(response);
  }

  throw new Error();
};

const getJSON = async <T>({
  url,
  fetchParams = {},
  handleError = {},
}: RequestProps): Promise<T> => {
  return request(url, fetchParams)
    .then(parseJson)
    .catch(error => handleError[error.status]?.()) as Promise<T>;
};

const getHTML = async <T>({
  url,
  fetchParams = {},
  handleError = {},
}: RequestProps): Promise<T> => {
  const newFetchParams = {
    ...fetchParams,
    headers: {
      ...(fetchParams?.headers ?? {}),
      ...defaultHTMLHeaders,
    },
  };

  return request(url, newFetchParams)
    .then(parseHtml)
    .catch(error => handleError[error.status]?.()) as Promise<T>;
};

위의 코드는 앞서 언급한 문제점들을 해결한 코드이다.

먼저 첫 번째 보완점인 “에러 핸들링을 fetch util에서 위임”handleError 를 전달받아 catch 메서드에서 HTTP 상태코드에 따른 에러 핸들러를 호출해 에러 핸들링하게끔 수정하였다.

두 번째 보완점인 “다양한 Response Data type 파싱 문제”는 getJSON, getHTML 함수를 정의한 후, 각각 then메서드에서 parseJson, parseHTML을 실행해 데이터를 파싱하게끔 수정하였다.

현재는 JSON과 HTML만 정의했으나, 다른 여러 데이터 타입(EX. blob)에 대해서도 추가 메서드를 정의해 처리할 수 있기 때문에 확장성 있다고 볼 수 있다.

profile
지식은 누가 origin인지 중요하지 않다.

0개의 댓글