export function redirect(
/** The URL to redirect to */
url: string,
type?: RedirectType
): never {
type ??= actionAsyncStorage?.getStore()?.isAction
? RedirectType.push
: RedirectType.replace
throw getRedirectError(url, type, RedirectStatusCode.TemporaryRedirect)
}서버 컴포넌트에서 redirect() 를 사용하게 되면 nextRouterError를 따로 처리하고 있어 해당 에러 바운더리에서 처리되지 않습니다.
export function onCaughtError(
thrownValue: unknown,
errorInfo: ErrorInfo & { errorBoundary?: React.Component }
) {
// ... 코드 생략 ...
// Skip certain custom errors which are not expected to be reported on client
if (isBailoutToCSRError(thrownValue) || isNextRouterError(thrownValue)) return
}서버 액션
서버 액션에서 redirect() 를 사용하게 되면 다음과 같이 처리됩니다.1. 클라이언트에서 loginAction() 호출 (fetch 요청)
2. 서버에서 redirect('/login') → RedirectError를 throw
3. action-handler.ts의 catch 블록이 에러 캐치 ✅
4. isRedirectError(err) 확인 후 특별 처리
5. HTTP 응답에 x-action-redirect: /login;replace 헤더 설정
6. 클라이언트로 303 응답 전송
7. 클라이언트의 server-action-reducer.ts가 헤더 파싱
8. Next.js 라우터로 /login으로 이동
packages/next/src/server/app-render/action-handler.ts
export async function handleAction({
...
} catch (err) {
if (isRedirectError(err)) {
const redirectUrl = getURLFromRedirectError(err)
const redirectType = getRedirectTypeFromError(err)
// if it's a fetch action, we'll set the status code for logging/debugging purposes
// but we won't set a Location header, as the redirect will be handled by the client router
res.statusCode = RedirectStatusCode.SeeOther
metadata.statusCode = RedirectStatusCode.SeeOther
if (isFetchAction) {
return {
type: 'done',
result: await createRedirectRenderResult(
req,
res,
host,
redirectUrl,
redirectType,
ctx.renderOpts.basePath,
workStore,
requestStore.url.pathname
),
}
}서버 컴포넌트
1. 서버가 페이지 렌더링 시작2. redirect('/login') → RedirectError throw
3. app-render.tsx가 catch
4. HTTP 307 + Location: /login 응답
5. 브라우저가 /login으로 자동 이동
packages/next/src/server/app-render/app-render.tsx
async function renderToStream(
...
} else if (isRedirectError(err)) {
errorType = 'redirect'
res.statusCode = getRedirectStatusCodeFromError(err)
metadata.statusCode = res.statusCode
const redirectUrl = addPathPrefix(
getURLFromRedirectError(err),
basePath
)