• 2021. 11. 2.

    by. 문익점

    반응형

    에러처리 방법

    AsyncBoundary를 이용해서 컴포넌트에서 일어나는 에러처리를 외부로 위임 했었습니다. Errorboundary는 Props로 Error 객체를 받을 수 있기 때문에 status code, flag, desc등 서버에서 주는 플래그에 따라 원하는 컴포넌트를 랜더링 할 수 있습니다. 이 포스팅에서는 AsyncBoundary를 이용하여 데이터 패칭을 하다 오류 발생 시 플래그에 따라 어떻게 처리 할 것인지에 대한 내용입니다.

    다음 내용들은 AsyncBoundary의 구현체를 알고 동작 방식을 알아야 이해가 가능하므로 읽어주시면 감사하겠습니다.

    맨 처음 데이터를 불러오다가 발생하는 에러

    function FetchErrorPage() {
    return (
    <AsyncBoundary
    ErrorFallback={(props) => <DisplayError {...props} />}
    SuspenseFallback={<div>...loading</div>}
    >
    <ErrorHandle />
    </AsyncBoundary>
    );
    }
    export default FetchErrorPage;

    먼저 AsnycBoundary를 사용한 모습입니다. ErrorHandle컴포넌트 안에서 비동기 셀럭터를 이용하여 데이터 패칭이 일어나고 에러가 발생한 경우 바로 AsyncBoundary가 그 처리를 위임 받습니다. 즉 DisplayError 컴포넌트 안으로 에러 객체가 전달되게 됩니다. 데이터 패칭 후 다음과 같은 에러가 발생 했다고 하겠습니다.

    status code는 404, response body는 다음과 같이 리턴을 받았습니다. 이 처리를 DisplayError 컴포넌트 안에서 처리하는 방법입니다.

    type DisplayErrorProps = {} & FallbackProps;
    interface ErrorBody {
    code: number;
    message: string;
    description: string;
    }
    function isAxiosError(res: unknown): res is AxiosError<ErrorBody> {
    if (typeof res !== "object" || res == null) {
    return false;
    }
    return true;
    }
    function DisplayError({ error, resetErrorBoundary }: DisplayErrorProps) {
    const [desc, setDesc] = useState("");
    useEffect(() => {
    // custom error handling
    if (isAxiosError(error) && error.response) {
    setDesc(error.response.data.description);
    }
    }, []);
    return (
    <div role="alert">
    <p>에러가 발생 했습니다!</p>
    <pre>{desc}</pre>
    <button onClick={() => resetErrorBoundary()}>다시 시도</button>
    </div>
    );
    }

    DisplayError 구현체입니다. Props로 error 객체를 이어 받고 있습니다. 이 Error 객체는 isAxiosError함수를 이용해서 AxiosError 인지를 판단하고 참일 시 response body에 담겨 있는 description를 desc에 담아줍니다. 그렇게 된다면 <pre>{desc}</pre>에서 검색 결과를 찾을 수 없습니다.를 랜더링하게 됩니다.

    사용자가 api call를 요청하고 난 뒤 에러

    사용자가 로그인, 로그아웃등 버튼을 클릭하거나 특정한 경우에 api call를 컴포넌트에서 요청하는 경우가 있습니다. 아래를 봅시다.

    function useErrorBoundary<ErrorType extends Error>() {
    const [error, setError] = useState<ErrorType | null>(null);
    if (error != null) {
    throw error;
    }
    return setError;
    }
    function ErrorHandle({}: ErrorHandleProps) {
    const setError = useErrorBoundary();
    const fetchData = async () => {
    try {
    await TestingService.fetchError();
    } catch (error) {
    if (isAxiosError(error)) {
    switch (error.response?.data.description) {
    case "잘못된 이메일 형식":
    return setError(error);
    case "anythong" :
    return "아무처리나하세요!"
    default:
    return setError(error);
    }
    }
    }
    };
    return (
    <div>
    <button onClick={fetchData}>API 통신</button>
    </div>
    );
    }

    ErrorHandle 구현체를 보면 isAxiosError를 이용하여 AxiosError를 체크 한 뒤에 그에 따른 description에 따라 에러 처리를 하고 있습니다. useErrorBoundary custom hook을 이용하고 있는데 이 hook은 단순이 에러를 던지는 기능을 합니다. 즉 catch로 잡은 에러를 다시 외부로 위임시키기 위해 throw error를 사용합니다.

    즉 다시 에러 객체는 외부로 위임 되게 되고 AsyncBoundary의 fallback으로 지정한 컴포넌트가 에러 객체를 받게 됩니다.

    정리

    AsyncBoundary를 이용하게 되면 데이터 팬딩 중 랜더링 처리와 에러처리를 외부로 위임하므로써 내부 컴포넌트 로직을 신경 쓸 수 있으며 에러 객체를 활용하여 에러 핸들링이 쉽게 가능합니다.

    refs

    https://jbee.io/react/error-declarative-handling-3/

     

    반응형