문제 상황
export const getServerSideProps = async (): Promise<
GetServerSidePropsResult<data>
> => {
try {
const data = await API호출();
return {
props: {
data,
},
};
} catch {
return {
//401 에러 처리..
//500 에러 처리..
redirect: {
destination: "/500",
permanent: false,
},
};
}
};
기존의 서버사이드렌더링의 경우, 일반적인 오류들에 대해서 처리를 하는 로직이 공통되는 부분들이 많다. 기본적으로 페이지 렌더링 과정에서 GET 요청에서도 사용자의 인가가 필요한 부분에서는 401 에러에 대한 처리를 해주고, 500에러 등 처리를 해줘야 하는 부분에 대해서 500 에러 처리를 해야 하다 보니까 결국 보일러플레이트가 많아지는 문제가 생기게 된다.
해결하기
api 호출 함수를 받아 일반적인 에러를 처리하는 로직을 처리할 수 있도록 고차함수를 만들어서 서버사이드 렌더링 과정에서 범용적으로 사용할 수 있도록 개선했다.
import { AxiosResponse, AxiosPromise, isAxiosError } from "axios";
import { GetServerSidePropsResult, GetServerSidePropsContext } from "next";
const LOGIN_PATH: string = "/login";
export async function withCheckInServer<T>(
fetchCall: () => AxiosPromise<T>,
options?: {
// 404 대신 다른 처리를 원할 때
onError?: (
// eslint-disable-next-line no-unused-vars
error: unknown,
// eslint-disable-next-line no-unused-vars
context?: GetServerSidePropsContext
) => GetServerSidePropsResult<T>;
// 에러 로깅 비활성화
context?: GetServerSidePropsContext;
}
): Promise<GetServerSidePropsResult<T>> {
const { onError, context } = options || {};
try {
// fetchCall이 함수인지 확인
if (typeof fetchCall !== "function") {
throw new Error(
"fetchCall must be a function that returns an AxiosPromise"
);
}
const response: AxiosResponse<T> = await fetchCall();
// 응답 데이터 검증
if (typeof response !== "object") {
throw new Error("Invalid response format");
}
return {
props: response.data, // response.data를 사용해야 함
};
} catch (error) {
if (isAxiosError(error)) {
const status = error.response?.status;
switch (status) {
case 401:
case 403:
return {
redirect: {
destination: LOGIN_PATH,
permanent: false,
},
};
case 404:
return {
notFound: true,
};
case 500:
return {
redirect: {
destination: "/500",
permanent: false,
},
};
}
}
// 커스텀 에러 핸들러가 있는 경우
if (onError) {
return onError(error, context);
}
// 기본 처리: 404
return {
redirect: {
destination: "/500",
permanent: false,
},
};
}
}기존의 API 호출 로직에 대해 공통되는 부분들에 대해서 모두 재사용을 방지할 수 있는 만큼, 훨씬 편해졌다.