단페스타
Fetch API 고쳐쓰기

Fetch API 고쳐쓰기

2024년 4월 22일 by이호연
thumbnail.webp

Vercel 팀은 Next JS에서 Fetch API를 래핑하여 브라우저와 서버에서 캐싱을 지원하는 fetch 함수를 만들었다. 이 함수는 브라우저와 서버에서 동일한 코드로 데이터를 가져올 수 있게 해준다. 하지만 이 함수는 다른 api 클라이언트 라이브러리들 만큼 편리하지는 않다.

기본 사용법

fetch 함수는 기본적으로 다음과 같이 사용할 수 있다.

const response = await fetch('/user/me');
const data = await response.json();

이 코드는 /user/me에서 데이터를 가져와서 data 변수에 저장한다. 하지만 이 코드는 400 ~ 500 사이의 HTTP 상태 코드를 받으면 에러를 던지지 않는다.

Error를 던지는 fetch 함수 만들기

그래서 나는 이를 해결하기 위해 assert 함수를 만들었다. 이 함수는 Response 객체를 받아서 HTTP 상태 코드에 따라 에러를 던진다.

export default function assertAPI(response: Response) {
  if (!response.ok) {
    switch (response.status) {
      case 400:
        throw new Error(BAD_REQUEST);
      case 401:
        throw new Error(UNAUTHORIZED);
      // ...
      case 500:
        throw new Error(SERVER_ERROR);
      default:
        throw new Error(UNKNOWN);
    }
  }
}

이 함수를 사용하면 다음과 같이 fetch 함수를 만들 수 있다.

export async function cfetch(url: string): Promise<any> {
  const response = await fetch(url);
  assertAPI(response);
 
  return response.json();
}

이제 우리의 fetch는 400 ~ 500 사이의 HTTP 상태 코드를 받으면 에러를 던진다.

Type-safe한 fetch 함수 만들기

fetch 함수를 사용할 때 가장 불편한 점은 type-safe 하지 않다는 것이다. fetch 함수는 Response 객체를 반환하는데, 이 객체는 어떤 데이터를 가지고 있는지 알 수 없다. 이를 해결하기 위해 fetch 함수를 다음과 같이 고쳤다.

export async function cfetch<Res>(url: string) {
  const response = await fetch(url);
  assertAPI(response);
 
  return response.json() as Promise<Res>;
}

반복되는 코드 줄이기

fetch 함수를 사용할 때마다 fetch().then(res => res.json())를 쓰는 것이 불편했다. 또, 메서드를 매번 지정해주는 것도 가독성을 떨어뜨렸다. 그래서 다음과 같이 fetch 함수를 고쳐썼다.