반응형

실제로 프로젝트를 사용할땐 순수 fetch를 사용하기 보단 axios같은 라이브러리를 주로 사용하지만, 작은 규모의 프로젝트나 라이브러리를 쓰지 않고 구현할 때 등등 종종 fetch를 사용할때가 있다.

fetch 란?

기본적인 fetch의 사용방법은 아래와 같다.

fetch('http://example.com/movies.json')
  .then(function(response) {
    return response.json();
  })
  .then(function(myJson) {
    console.log(JSON.stringify(myJson));
  });

 

에러처리

axios만 주로 사용하다 보면 놓치기 쉬운 axios와 fetch의 차이점은, fetch는 HTTP Status가 400/500등의 에러코드를 뱉어내도 error상태를 반환하지 않는다.


잘못된 주소로 요청한 예시
존재하지 않는 주소값으로 요청을 보내도 catch단에서 에러가 확인되지 않는다.


API가 존재하지 않는 주소로 요청한 예시
아예 fetch의 요청이 실패되거나 하는 상황에서만 error를 잡을 수 있다. (조금 더 눈에 띄라고 error를 console.warn로 작성했다.)

그럼 이때 404 error, 500 error같은 상황에서 어떻게 판별해야 할까?

fetch()로 부터 반환되는 Promise 객체는 HTTP error 상태를 reject하지 않습니다. HTTP Statue Code가 404나 500을 반환하더라도요. 대신 ok 상태가 false인 resolve가 반환되며, 네트워크 장애나 요청이 완료되지 못한 상태에는 reject가 반환됩니다. ㅡ MDN

response.ok를 사용하면 알 수 있다. 요청이 정상적으로 성공하면 response.ok가 true로 나오지만, 실패한 경우 false로 나타난다.


요청이 성공한 경우


요청이 실패한 경우

이를 이용해 에러를 처리할 수 있다.

이렇듯 fetch는 요청 자체가 실패한 경우를 제외하고선 catch로 error가 넘어가지 않으니, 꼭 response를 받아오는 첫번째 요청에서 response.ok로 error를 확인하고 catch에서 잡아오도록 작성하는 습관을 들이자!
추가로, 예시에서는 간단한 예시를 위해 console.log에서만 에러메세지를 표시하도록 해뒀지만 실제로 사용할때는 최소한 alret이라도 이용해 사용자에게 에러메세지를 표시하는걸 잊지 않도록 하자. (Promise를 사용할 경우에는 then에 이어 catch까지 사용해주는걸 까먹지 않도록 하자..)

 

 

React Query에서 `onError`와 `onSuccess` 핸들러가 동작하는 조건

1.  `onError` 핸들러:  Promise가 reject된 경우 
    -   API 요청이 실패한 경우: 네트워크 오류, HTTP 응답 상태 코드가 4xx나 5xx 범위인 경우 등 모든 요청 실패 상황에 해당한다. 이때 `throw new Error()`를 사용하거나, Promise가 reject되는 방식으로 오류를 처리해야 한다.


2.  `onSuccess` 핸들러:  Promise가 resolve된 경우
    -   API 요청이 성공적으로 완료된 경우: HTTP 응답 상태 코드가 2xx 범위인 경우이다. 즉, 성공적인 응답을 받았을 때 호출된다.

 

 

React-query와 fetch 

import { useQuery, useMutation, useQueryClient } from "react-query";

interface Post {
  id: number;
  title: string;
}

function ReactQuery() {
  const queryClient = useQueryClient();

  const handleUpdatePost = async (
    postId: number,
    updatedTitle: string
  ): Promise<void> => {
    await updatePost(postId, updatedTitle);
    queryClient.refetchQueries("posts");
  };
  const createPostMutation = useMutation(
    async (newPost: Post) => {
      const response = await fetch("http://localhost:3001/posts", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify(newPost),
      });
      if (!response.ok) {
        console.log(response);
        throw new Error("API 요청에 실패했습니다.");
      }
      return response.json();
    },
    {
      onError: (error) => {
        console.log("API 요청 실패:", error);
      },
      onSuccess: () => {
        queryClient.invalidateQueries("posts");
      },
    }
  );
}

export default ReactQuery;

 

위의 코드에서 fetch를 통해 200 ok가 아닌 다른 다른 response를 받더라도, fetch는 오류를 뱉지 않으므로 onSuccess가 호출되게 된다.

 

따라서 response.ok 를 확인하여 onSuccess가 아닌 onError로 보내는 Error를 throw하여야 한다.

 

 

 

https://velog.io/@yukyung/fetch%EC%9D%98-%EC%97%90%EB%9F%AC%EC%B2%98%EB%A6%AC-%EC%9D%B4%EC%95%BC%EA%B8%B0

 

반응형