API/Functions/redirect

김동현·2026년 3월 9일

next.js 공식문서 번역

목록 보기
79/79

title: redirect
description: redirect 함수에 대한 API 레퍼런스입니다.
url: "https://nextjs.org/docs/app/api-reference/functions/redirect"
version: 16.1.6
lastUpdated: 2026-02-27
prerequisites:


redirect 함수를 사용하면 사용자를 다른 URL로 리다이렉트(이동) 시킬 수 있어요. 이 함수는 서버 및 클라이언트 컴포넌트, 라우트 핸들러, 그리고 서버 함수에서 렌더링을 하는 도중에 다양하게 사용할 수 있답니다.

스트리밍 컨텍스트에서 사용할 때는, 클라이언트 측에서 리다이렉트를 실행하도록 메타 태그를 삽입하는 방식으로 동작해요. 반면, 서버 액션(Server Action) 안에서 사용하면 함수를 호출한 쪽으로 303 HTTP 리다이렉트 응답을 반환하고, 그 외의 일반적인 상황에서는 307 HTTP 리다이렉트 응답을 반환하게 됩니다.

💡 강사의 팁!
"303이나 307 같은 숫자가 뭐지?" 싶으실 수도 있어요. 이건 HTTP 상태 코드라는 건데, 프론트엔드 개발자 기술 면접에서 아주 자주 물어보는 단골 질문이랍니다! 302 대신 왜 307을 쓰는지에 대한 이유를 이 문서 하단 FAQ에서 자세히 다루고 있으니, 면접 준비한다고 생각하시고 꼭 눈여겨봐 두세요!

만약 찾으려는 리소스나 데이터가 존재하지 않는 상황이라면, redirect 대신에 notFound 함수를 사용하는 것이 훨씬 자연스럽고 올바른 처리 방법이에요.

레퍼런스 (Reference)

매개변수 (Parameters)

redirect 함수는 두 가지 인자를 받습니다:

redirect(path, type)
매개변수타입설명
pathstring리다이렉트할 목적지 URL이에요. 상대 경로(/login 등)나 절대 경로(https://... 등) 모두 가능해요.
type'replace' (기본값) 또는 'push' (서버 액션에서의 기본값)수행할 리다이렉트의 종류를 결정하는 타입이에요.

기본적으로 redirect서버 액션 내에서는 브라우저의 방문 기록(히스토리 스택)에 새로운 기록을 추가하는 push 방식을 사용하고, 그 외의 모든 곳에서는 현재 URL을 대체해 버리는 replace 방식을 사용해요. 만약 이 동작 방식을 바꾸고 싶다면 type 파라미터를 직접 지정해서 덮어씌울 수 있답니다.

RedirectType 객체는 이 type 파라미터에 쓸 수 있는 옵션들을 담고 있어요.

import { redirect, RedirectType } from 'next/navigation'

redirect('/redirect-to', RedirectType.replace)
// 또는
redirect('/redirect-to', RedirectType.push)

💡 강사의 팁!
pushreplace의 차이는 사용자 경험(UX) 측면에서 아주 중요해요! push로 이동하면 사용자가 브라우저 '뒤로 가기' 버튼을 눌렀을 때 이전 페이지로 돌아올 수 있지만, replace를 쓰면 이전 페이지 기록을 덮어씌우기 때문에 뒤로 가기를 눌러도 돌아오지 않아요. 포트폴리오 프로젝트에서 로그인 후 메인 화면으로 넘어갈 때 등 상황에 맞게 골라 쓰는 센스가 필요합니다.

참고로, 서버 컴포넌트 안에서는 이 type 파라미터를 입력해도 아무런 영향을 미치지 않으니 알아두세요!

반환값 (Returns)

redirect는 아무런 값도 반환하지 않아요.

동작 방식 (Behavior)

  • 서버 액션이나 라우트 핸들러에서 try/catch 문을 사용할 때, redirect는 반드시 try 블록 바깥에서 호출되어야 해요.
  • 왜냐하면 redirect는 내부적으로 에러를 발생(throw)시키는 방식으로 동작하기 때문이에요. 만약 try 블록 안에서 쓴다면 catch 블록이 이 리다이렉트 에러를 일반적인 에러처럼 잡아버려서 페이지 이동이 일어나지 않는답니다. 그래서 무조건 try/catch바깥에 두어야 해요!

    💡 강사의 팁!
    실무나 개인 프로젝트를 하실 때, 이 부분에서 정말 많은 분들이 헤맵니다. "에러 처리를 잘해놨는데 왜 리다이렉트가 안 되지?" 싶을 때 확인해보면 십중팔구 try 블록 안에 redirect()가 들어있어요. 이런 디테일을 챙기는 것이 실력입니다!

  • 307(임시) HTTP 리다이렉트 대신에 308(영구) HTTP 리다이렉트를 반환하고 싶으시다면, redirect 대신 permanentRedirect 함수를 사용하시면 돼요.
  • redirect는 클라이언트 컴포넌트가 렌더링되는 과정 중에도 호출될 수 있어요. 하지만 버튼 클릭 같은 이벤트 핸들러 안에서는 쓸 수 없답니다. 이벤트 핸들러 안에서 페이지를 이동시켜야 한다면 useRouter을 활용해 주세요.
  • redirect는 절대 경로 URL도 인자로 받을 수 있기 때문에 사용자를 외부 링크로 보낼 때도 아주 유용해요.
  • 만약 화면 렌더링 과정이 시작되기도 전에 아예 접근을 막고 리다이렉트를 시켜버리고 싶다면, next.config.js 파일을 설정하시거나 미들웨어(Proxy)를 사용하시는 것이 더 좋은 방법입니다.

예제 (Example)

서버 컴포넌트 (Server Component)

redirect() 함수를 호출하면 내부적으로 NEXT_REDIRECT라는 에러를 던지게 되고, 그 함수가 호출된 라우트 세그먼트의 렌더링을 즉시 멈추게 돼요.

import { redirect } from 'next/navigation'

async function fetchTeam(id: string) {
  const res = await fetch('https://...')
  if (!res.ok) return undefined
  return res.json()
}

export default async function Profile({
  params,
}: {
  params: Promise<{ id: string }>
}) {
  const { id } = await params
  const team = await fetchTeam(id)

  if (!team) {
    redirect('/login')
  }

  // ...
}
import { redirect } from 'next/navigation'

async function fetchTeam(id) {
  const res = await fetch('https://...')
  if (!res.ok) return undefined
  return res.json()
}

export default async function Profile({ params }) {
  const { id } = await params
  const team = await fetchTeam(id)

  if (!team) {
    redirect('/login')
  }

  // ...
}

알아두면 좋은 점 (Good to know): redirect는 TypeScript의 never 타입을 활용하기 때문에, 코드 작성 시 return redirect() 처럼 리턴 값으로 쓸 필요가 없어요. 그냥 redirect()만 딱 호출해 주면 됩니다.

클라이언트 컴포넌트 (Client Component)

redirect는 클라이언트 컴포넌트 안에서도 직접 쓸 수 있어요.

'use client'

import { redirect, usePathname } from 'next/navigation'

export function ClientRedirect() {
  const pathname = usePathname()

  if (pathname.startsWith('/admin') && !pathname.includes('/login')) {
    redirect('/admin/login')
  }

  return <div>Login Page</div>
}
'use client'

import { redirect, usePathname } from 'next/navigation'

export function ClientRedirect() {
  const pathname = usePathname()

  if (pathname.startsWith('/admin') && !pathname.includes('/login')) {
    redirect('/admin/login')
  }

  return <div>Login Page</div>
}

알아두면 좋은 점 (Good to know): 초기 페이지가 로드될 때 서버 사이드 렌더링(SSR)이 진행 중이라면, 클라이언트 컴포넌트 안에서 redirect를 사용하더라도 서버 측 리다이렉트로 깔끔하게 처리됩니다.

redirect는 서버 액션을 통해 클라이언트 컴포넌트에서 활용될 수도 있어요. 사용자가 폼을 제출하거나 버튼을 클릭하는 등의 이벤트를 통해 리다이렉트해야 한다면, 그때는 useRouter 훅을 사용해 주시면 됩니다.

'use client'

import { navigate } from './actions'

export function ClientRedirect() {
  return (
    <form action={navigate}>
      <input type="text" name="id" />
      <button>Submit</button>
    </form>
  )
}
'use client'

import { navigate } from './actions'

export function ClientRedirect() {
  return (
    <form action={navigate}>
      <input type="text" name="id" />
      <button>Submit</button>
    </form>
  )
}
'use server'

import { redirect } from 'next/navigation'

export async function navigate(data: FormData) {
  redirect(`/posts/${data.get('id')}`)
}
'use server'

import { redirect } from 'next/navigation'

export async function navigate(data) {
  redirect(`/posts/${data.get('id')}`)
}

자주 묻는 질문 (FAQ)

redirect는 307과 308을 사용할까요?

redirect() 함수를 사용하시다 보면, 임시 리다이렉트에는 307이, 영구 리다이렉트에는 308이라는 상태 코드가 쓰인다는 걸 알게 되실 거예요.

원래 전통적으로는 임시 리다이렉트에 302를, 영구 리다이렉트에는 301을 많이 사용했어요. 하지만 많은 브라우저들이 302 리다이렉트를 처리할 때, 애초에 클라이언트가 어떤 HTTP 메서드로 요청했는지와는 상관없이 POST 요청을 강제로 GET 요청으로 바꿔서 재요청하는 문제가 있었답니다.

예를 들어볼게요. /users라는 주소에서 /people이라는 주소로 리다이렉트되는 상황입니다. 여러분이 새로운 유저를 생성하기 위해 /usersPOST 요청을 보냈는데, 서버가 302 임시 리다이렉트 응답을 주었다고 가정해 볼까요? 그러면 브라우저는 /people로 이동할 때 요청 메서드를 POST에서 GET으로 멋대로 변경해 버려요. 새로운 유저를 '생성'해야 하니까 당연히 /people에도 똑같이 POST 요청을 보내는 게 맞는데 말이죠!

이런 어이없는 문제를 해결하기 위해 등장한 것이 바로 307 상태 코드입니다. 307을 사용하면 처음 보냈던 POST 메서드를 그대로 보존할 수 있거든요.

  • 302 - 임시 리다이렉트이지만, 브라우저가 요청 메서드를 POST에서 GET으로 변경해버릴 수 있어요.
  • 307 - 임시 리다이렉트이면서, 처음 요청했던 POST 메서드를 안전하게 보존해 줍니다.

그래서 redirect() 메서드는 불안정한 302 대신에 기본적으로 307을 사용합니다. 덕분에 여러분의 소중한 요청은 항상 본래의 POST 요청 상태를 잃지 않고 지켜질 수 있게 되었답니다.

💡 강사의 팁!
"HTTP 상태코드 301/302와 307/308의 차이점이 무엇인가요?" 라는 질문, 기술 면접 단골 소재인 거 아시죠? 이 공식 문서의 설명이 바로 그 정답입니다. POST 메서드를 보존해 주느냐 아니냐의 차이! 이 부분은 머릿속에 꼭 각인시켜 두셨다가 면접관님 앞에서 자신 있게 대답하시면 좋은 점수를 받으실 수 있을 거예요.

HTTP 리다이렉트에 대해 더 깊이 공부하고 싶으시다면 MDN 문서를 참고해 보세요!

버전 기록 (Version History)

버전변경 사항
v13.0.0redirect 기능이 처음 도입되었어요.
  • permanentRedirect
    • permanentRedirect 함수에 대한 API 레퍼런스 문서입니다.

모든 공식 문서의 의미론적 개요(semantic overview)를 보시려면 여기를 클릭해서 사이트맵(sitemap.md)을 확인해 주세요.

이용 가능한 모든 공식 문서의 목차(index)를 확인하시려면 여기를 클릭해서 llms.txt를 확인해 주세요.

profile
프론트에_가까운_풀스택_개발자

0개의 댓글