2025-01-16
nextjs로 과제를 진행 중에 만나게 된 상황입니다. 예전 개인 프로젝트에서도 server action으로 nextauth의 로그인 처리 후 리다이렉션이 원하는 데로 되지 않아서 다른 방법을 선택했었는데, 이번 기회에 제대로 분석 후에 문제를 해결했습니다.
[현재 상황]
[문제점]
[알게 된 점]
Server Component
Invoking the redirect() function throws a NEXT_REDIRECT error and terminates rendering of the route segment in which it was thrown.
[파훼법]
해당 문제를 겪고 있는 분들이 생각보다 많았습니다. 레딧, nextjs github issue페이지등에서 해당 문제를 해결한 코멘트들을 분석해 보았습니다.
1. try, catch문 밖으로 redirect를 옮기기
성공, 실패에 대한 flag를 변수로 만들고, try, catch문을 통과하면서 변동된 flag에 따라 redirect를 실행하지 결정하는 방법
let success = false;
try {
// ... 데이터 패칭 작업
success = true;
} catch (error) {
}
if (success) redirect('/');
2. 커스텀 에러를 일으켜서 catch문에서 redirect 하도록 작성
redirect를 try문에서 쓰지 않고, redirect를 해야 하는 조건에 커스텀 에러를 throw 해서 catch문에 해당 에러를 판별 후 redirect
try {
const detail = await getProduct(id);
const isOwner = detail.ownerId === session.user.id;
if (!isOwner) {
throw new Error("NO_PERMISSION");
}
return (
<Component data={data} />
);
} catch (error) {
if (isAxiosError(error)) {
if (error.status === 404) {
notFound();
}
}
if (error instanceof Error) {
if (error.message === "NO_PERMISSION") {
redirect("/items");
}
}
throw new Error("페이지 정보를 가져오는데 문제가 생겼습니다.");
}
3. redirect의 에러일 경우에 catch문에서 다시 error를 전파하도록 작성
isRedirectError로 에러 타입을 확인 후 그대로 다시 error를 throw 하도록 하는 방법
try {
const detail = await getProduct(id);
const isOwner = detail.ownerId === session.user.id;
if (!isOwner) {
redirect("/items");
}
return (
<Component data={data} />
);
} catch (error) {
if (isAxiosError(error)) {
if (error.status === 404) {
notFound();
}
}
// 그냥 바로 error를 throw해줘도 상관없다.
if (isRedirectError(error)) {
throw error;
}
throw new Error("페이지 정보를 가져오는데 문제가 생겼습니다.");
}
저는 3번이 더 편해 보여서 해당 방법을 차용해서 문제를 해결했습니다.
[더 나아가]