본문 바로가기
카테고리 없음

Axios Interceptor에서 상태 값에 따른 라우트 이동시키기 (feat. 글로벌 네비게이터)

by klm hyeon woo 2024. 12. 15.

목차

· 글을 시작하며

· 이 불편함을 어떻게 해소할 수 있을까?

· 글을 마치며


글을 시작하며

Axios Interceptor은 Axios에 관련된 통신을 할 때, 중간에 통신을 가로채 개발자가 데이터 패칭 동작에 대한 커스텀 동작을 추가할 수 있어요. 데이터 패칭 함수에 공통적인 동작을 추가해야하는 작업은 굉장히 번거롭고, DX를 해치는 과정이 될 수 있습니다. 그렇기 때문에 관련 동작에 대한 부분들은 Axios Interceptor를 통해서 이러한 공통적인 동작에 대한 제어를 진행해야해요.

 

다만, Axios Interceptor 파일의 경우 .js , .ts 로 구성이 되기 때문에 SPA의 페이지를 이동하는 훅인 useNavigate 를 사용할 수 없어요.

React 훅은 컴포넌트 안에서 사용이 된다는 규약을 가지고 있죠. 이 때문에 데이터 패칭 후 예를 들어 401 에러 코드가 발생했을 때, 각 함수의 공통 로직에서 처리를 해야한다는 불편함을 가지고 있습니다.

이 불편함을 어떻게 해소할 수 있을까?

각 데이터 패칭 함수에 status 에 대한 분기처리를 통해 처리하는 것은 매우 불편한 일이에요. useNavigate 는 컴포넌트 내부에서 호출이 되고, Axios Interceptor 또한 컴포넌트 외부에서 설정되므로 useNavigate 를 직접 사용할 수 없습니다. 그래서 이를 위해 useNavigate 와 같은 라우팅 동작을 트리거할 수 있는 방식으로 사용을 해야해요.

첫 번째, navigate 를 글로벌 함수로 사용해요

React Router의 useNavigate 를 글로벌 함수로 사용할 수 있도록 구현할 수 있습니다.

let globalNavigate: ReturnType<typeof import("react-router-dom").useNavigate>;
 
const setGlobalNavigate = (navigate: typeof globalNavigate) => {
    globalNavigate = navigate;
};
 
const navigateTo = (path: string) => {
    if (globalNavigate) {
        globalNavigate(path);
    } else {
        console.log("navigateTo Function was called before navigate was initialized");
    }
}
 
export { setGlobalNavigate, navigateTo };

두 번째, 라우터 초기화 시에 setGlobalNavigate 설정을 해요

App.tsx 또는 라우터를 초기화하는 최상위 컴포넌트에서 useNavigate 를 설정합니다.

import { setGlobalNavigate } from "@/path/to/api";
 
const App = () => {
    const navigate = useNavigate();
     
    useEffect(() => {
        setGlobalNavigate(navigate);
    }, []);
     
    return <Components/>;
};

세 번째, Axios Interceptor 인터셉터에서 활용을 해요

인터셉터의 onErrorResponse (예시)에서 navigateTo 함수를 호출합니다.

const onErrorResponse = (error: AxiosError | Error) => {
    if (axios.isAxiosError(error)) {
        const { status } = error?.response as AxiosResponse;
         
        switch (status) {
                case 401: {
                    navigateTo("/login");
                    onError(status, "인증을 실패했어요");
                    break;             
                }
                default: {
                    onError(status, "기타 에러가 발생했습니다");
                }
        }
    })
    return Promise.reject(error);
}

// 여기서 onError 라는 함수는 `status`와 `message`를 인자로 받는 단순 에러 로그 출력 함수를 의미해요

글을 마치며

setGlobalNavigate  navigateTo 를 활용하여 Axios 인터셉터 내부에서도 React Router  useNavigate 와 동일한 동작을 수행할 수 있습니다. 401 Unautorized 가 발생했을 때 위와 같은 예제처럼 조건식을 통해 우리가 평소 사용하는 메서드처럼 편하게 자동으로 로그인 페이지로 이동시킬 수록 구현할 수 있습니다.

 

이렇게 전역 네비게이터를 통해 더 이상 각각의 데이터 페칭 함수에 에러처리를 통해 로그인 페이지로 보내는 것이 아닌, 단 한번의 설정을 통해 관련 처리를 공통화 시킬 수 있다는 점에서 충분히 프론트엔드 DX 향상에 기여를 할 수 있다고 봅니다.

댓글