본문 바로가기
우아한 테크코스

프론트엔드의 에러핸들링

by 해-온 2023. 6. 6.

 

이번 미션을 진행하면서, 에러핸들링을 어떻게 해야 할지 고민이 많았다.

서버와 통신도 같이 하면서 여러 가지 에러가 생겨났고, 그중에는 내가 통제할 수 없는 부분도 있었다.

이번 글을 작성하면서 에러가 정확히 무엇인지 알아보고, 에러 핸들링을 프론트엔드 단에서는 어떻게 할 수 있는지, 사용자에게 어떻게 알려야 하는지 등에 대해 작성해 보려고 한다.

 

에러란?

하드웨어의 고장 또는 소프트웨어가 본래의 동작을 할 수 없는 상태를 말한다. 

 

에러의 분류

  1. 예측할 수 있는 에러
  2. 예측 불가능한 에러

크게 두 가지로 나누어 볼 수 있다.

 

예측할 수 있는 에러

서버 API로 전달받는 에러 중 상태코드로 예측할 수 있는 에러

사용자 입력 에러

인증 에러

없는 페이지에 접근했을 때의 에러

 

예측 불가능한 에러

서버 API로 전달받는 에러 중 500대 에러

일시적으로 네트워크가 불안정할 때 발생하는 에러

서비스 장애

 

에러 핸들링이란?

에러 상황의 발생부터 종료까지의 흐름을 말한다.

에러 핸들링을 통해 프로그램에서 발생할 수 있는 예상치 못한 상황이나 오류에 대처할 수 있다.

오류가 발생하면서 서비스가 완전히 중단되는 것을 방지하고, 사용자에게 적절한 피드백을 제공하면서, 좋은 사용자 경험을 유지한다.

 

프론트엔드 에러 핸들링에서 중요한 것

프론트엔드의 에러 핸들링에서 중요한 것은 역시 사용자라고 생각한다. 

에러가 발생해도 사용자가 이용하는데 불편이 없어야 하고, 발생 사실을 인지할 수 있어야 한다.

에러 핸들링을 잘한다면 안정적인 서비스를 만들고 사용자 경험을 높일 수 있을 것이다.

 

프론트엔드에서의 에러 핸들링

try-catch

try 구문 안에는 에러가 발생할 수도 있는 로직을 작성한다. 

catch 구문에서는 에러를 잡는다.

 

    try {
      const response = await fetchProducts(hostName);
      return response;
    } catch (error) {
      console.error(error);
      throw error;
    }

 

여기서는 try 구문 안에서 상품 데이터를 get하고 그 데이터를 return 한다.

그 과정에서 에러가 발생한다면 catch 문을 통해 에러를 콘솔에 출력하고 던진다.

 

비동기 API 통신에서의 에러 핸들링

상태 코드를 통해 에러 핸들링이 가능하다.

 

export const fetchData = async <T>(
  url: string,
  options?: RequestInit
): Promise<T> => {
  const response = await fetch(url, options);

  if (!response.ok) {
    throw new Error(response.status.toString());
  }

  const data: T = await response.json();
  return data;
};

 

이 코드는 데이터를 get 해오는 유틸 함수이다.

만약, 응답에 문제가 있다면 해당 상태코드를 Error 객체에 담아 던진다.

 

사용자에게 어떻게 알려야 할까?

  1. alert
  2. 페이지 이동

 

이번 미션에서는 2가지 방법을 통해 사용자에게 에러 상황을 알렸다. 

먼저, 알람으로 띄운다. 최대한 상황을 사용자가 인지할 수 있도록 친절한 메시지를 더하는 것은 덤이다.

 

    if (userInputPoint > totalProductPrice) {
      alert('상품 금액을 초과하는 포인트 사용은 불가능합니다.');
      e.target.value = '';
      return;
    }

 

5,000원의 음료수를 구매한다고 생각해 보자.

이때 포인트를 5,000원을 초과한 금액을 사용할 수 없다.

따라서 사용자가 상품 가격을 초과하는 포인트를 사용하면 알람을 띄워 사용자에게 알린다.

또한, input 창을 비워 사용자가 따로 지울 필요 없이 다시 입력하도록 돕는다.

 

다음으로는 페이지 이동을 시킨다. 

 

    orderApi(hostName)
      .then((apiInstance) => {
        return apiInstance.postOrderProduct(orderData);
      })
      .then(() => {
        setCartProducts([]);
        setCheckedCartProduct([]);
        navigate('/orders/complete');
      })
      .catch(() => {
        navigate('/orders/fail');
      });

 

사용자가 주문하다 실패한다면 결제 실패 페이지로 이동시킨다.

만약, 이 과정이 없다면 API 요청이 실패하더라도 결제 페이지에서 사용자는 벗어날 수 없다.

따라서 결제에 실패했다는 것을, 페이지를 이동시켜 알리고 다음 행동을 유도하도록 만든다.

 

결론

에러 처리는 최대한 섬세하게 하는 것이 좋다.

여기에 작성한 방법 말고도 다양한 방식을 사용해 안전하게 구성한다면 보다 나은 서비스를 구현할 수 있을 것이다.

또한, 에러 메시지를 사용자가 이해하기 쉽도록 작성하고, 적절하게 대처할 수 있도록 유도한다면 더 우수한 사용자 경험을 제공할 수 있을 것이다.

댓글