티스토리 뷰

개요

프론트엔드 개발을 하면서 정상적으로 동작하는 UI 외에 에러가 발생했을 때 적절한 UI 및 페이지 이동을 통해 더 안정적이고 사용성을 고려한 서비스 개발이 필요 했습니다.

가장먼저, Error Boundary를 도입하고자 하였습니다.

https://ko.legacy.reactjs.org/docs/error-boundaries.html

다음 링크를 통해 간략한 에러발생 시나리오를 파악해보면

  1. 하위 컴포넌트에서 에러발생
  2. getDerivedFromError에서 fallback UI가 보이도록 설정해주고
  3. componentDidCatch를 통해 logging을 지원합니다.

다음은 링크를 참고하여 간략하게 작성한 APIErrorBoundary 코드 입니다.

// ApiErrorBoundary.tsx
import React, { PropsWithChildren } from 'react';
import { NetworkError, UnknownError } from '@/components';

type AuthErrorBoundaryState = {
  hasError: boolean;
};

export default class ApiErrorBoundary extends React.Component<
  PropsWithChildren<ApiErrorBoundaryProps>,
  AuthErrorBoundaryState
> {
  constructor(props: ApiErrorBoundaryProps) {
    super(props);
    this.state = { hasError: false };
  }

  static getDerivedStateFromError() {
    return { hasError: true };
  }

  //   Todo:connect monitoring api
  componentDidCatch(): void {}

  render() {
    if (!this.state.hasError) {
      return this.props.children;
    }

    if (this.props.error?.type === 'network') {
      return <NetworkError />;
    }

    return <UnknownError />;
  }
}

// UI.tsx
export default function TodayChallenge({ }: Props) {
  return (
    <ApiErrorBoundary> // ErrorBoundary 설정
      <Fetcher> 
        <Container />
      </Fetcher>
    </ApiErrorBoundary>
  );
}

그러나…

ErrorBoundary에 포착되지 않는 에러들이 있습니다.

  • 이벤트 핸들러 (더 알아보기)
  • 비동기적 코드 (예: setTimeout 혹은 requestAnimationFrame 콜백)
  • 서버 사이드 렌더링
  • 자식에서가 아닌 에러 경계 자체에서 발생하는 에러

Next.js를 사용하기 때문에 서버사이드에서의 에러처리를 따로 진행을 해주어야 했습니다.

저의 경우 yceffort님의 정리해주신 자료를 참고하여 코드를 작성하였습니다.

https://yceffort.kr/2021/10/api-error-handling-nextjs

next.js의 redirect관련해선 다음 링크를 참고 해주세요.

https://nextjs.org/docs/app/api-reference/functions/redirect.

import { GetServerSideProps, GetServerSidePropsContext } from 'next';
import { isInstanceOfAPIError } from '@/error';

export default function withGetServerSideProps(getServerSideProps: GetServerSideProps): GetServerSideProps {
  return async (context: GetServerSidePropsContext) => {
    try {
      const result = await getServerSideProps(context);

      return result;
    } catch (error) {
      if (isInstanceOfAPIError(error)) {
        const { redirectUrl, notFound } = error;

        if (notFound) {
          return {
            notFound: true,
          };
        }

        return {
          redirect: {
            destination: redirectUrl,
            permanent: false,
          },
        };
      }

      // handle on the client
      return {
        props: {},
        },
      };
    }
  };
}
  • redirect나 notFound의 값을 갖고 있는 Error 타입의 경우 특정 주소로 redirect할 수 있게 설정했습니다.
  • 클라이언트에서 처리하려는 경우 서버에서 에러가 나지않게 빈 객체를 보내주었습니다.

만약 getInitialProps를 사용하는 경우에는 다음 링크를 확인해주세요

https://stackoverflow.com/questions/59746476/redirecting-from-getinitialprops-in-error-js-in-nextjs

마지막으로..

// Container.tsx

const { error, isError } = useFetch();

if (isError) {
    throw error;
}

container component에서 에러가 발생하면 throw 하고 ErrorBoundary에 포착되어 필요한 UI를 보여주어 대응할 수 있도록 합니다.

참고

getInitialProps에서 redirect 작성하기

https://stackoverflow.com/questions/59746476/redirecting-from-getinitialprops-in-error-js-in-nextjs

에러 핸들링 참고 아티클

https://yceffort.kr/2021/10/api-error-handling-nextjs

nextjs redirect

https://nextjs.org/docs/app/api-reference/functions/redirect