How to handle redirects in Next.js

김동현·2026년 3월 4일

next.js 공식문서 번역

목록 보기
31/79

Next.js에서 리다이렉트를 처리하는 방법은 꽤 여러 가지가 있답니다. 이 문서에서는 우리가 사용할 수 있는 각각의 옵션들과 그 옵션들을 언제 사용하면 좋은지(유스케이스), 그리고 리다이렉트 규칙이 엄청나게 많아질 때 이를 어떻게 관리해야 하는지 하나씩 차근차근 살펴볼 거예요.

먼저 아래의 요약표를 통해 전체적인 큰 그림을 잡고 넘어가 볼까요?

API목적 (Purpose)사용 가능한 곳 (Where)상태 코드 (Status Code)
redirect데이터 변경(Mutation)이나 이벤트 발생 후 사용자 이동서버 컴포넌트, 서버 함수, 라우트 핸들러307 (임시) 또는 303 (서버 액션)
permanentRedirect데이터 변경이나 이벤트 발생 후 사용자 이동서버 컴포넌트, 서버 함수, 라우트 핸들러308 (영구)
useRouter클라이언트 사이드에서의 네비게이션(페이지 이동) 수행클라이언트 컴포넌트의 이벤트 핸들러 내부N/A (해당 없음)
redirects in next.config.js들어오는 요청의 경로(Path)를 기반으로 리다이렉트next.config.js 설정 파일 내부307 (임시) 또는 308 (영구)
NextResponse.redirect특정 조건에 따라 들어오는 요청을 리다이렉트Proxy (프록시)아무 상태 코드나 가능 (Any)

redirect 함수

redirect 함수는 사용자를 다른 URL로 이동시키고 싶을 때 사용해요. 서버 컴포넌트(Server Components), 라우트 핸들러(Route Handlers), 그리고 서버 함수(Server Functions) 안에서 이 redirect 함수를 호출할 수 있답니다.

보통 redirect는 데이터베이스의 값을 바꾸는 등 어떤 '작업(Mutation)'이나 이벤트가 끝난 직후에 자주 사용돼요. 예를 들어, 새로운 게시글을 작성하고 나서 그 작성된 게시글 페이지로 넘어가는 경우를 볼까요?

//filename="app/actions.ts" switcher
'use server'

import { redirect } from 'next/navigation'
import { revalidatePath } from 'next/cache'

export async function createPost(id: string) {
  try {
    // Call database
  } catch (error) {
    // Handle errors
  }

  revalidatePath('/posts') // Update cached posts
  redirect(`/post/${id}`) // Navigate to the new post page
}
//filename="app/actions.js" switcher
'use server'

import { redirect } from 'next/navigation'
import { revalidatePath } from 'next/cache'

export async function createPost(id) {
  try {
    // Call database
  } catch (error) {
    // Handle errors
  }

  revalidatePath('/posts') // Update cached posts
  redirect(`/post/${id}`) // Navigate to the new post page
}

💡 알아두면 좋은 팁 (Good to know):

  • redirect는 기본적으로 307 (임시 리다이렉트 - Temporary Redirect) 상태 코드를 반환해요. 하지만 서버 액션(Server Action) 안에서 사용될 때는 303 (See Other) 코드를 반환하게 되는데요, 이 303 코드는 POST 요청이 성공적으로 끝난 뒤에 결과 페이지(success page)로 리다이렉트 시킬 때 웹 표준으로 아주 흔하게 쓰이는 방식이랍니다.
  • redirect 함수는 내부적으로 에러(Error)를 던지는(throw) 방식으로 동작해요. 그래서 만약 try/catch 문을 사용 중이라면 반드시 try 블록 바깥에서 호출해야 합니다. 안 그러면 catch 블록이 리다이렉트를 에러로 착각하고 잡아버리거든요!
  • 클라이언트 컴포넌트에서도 렌더링 과정 중에는 redirect를 호출할 수 있어요. 하지만 버튼 클릭 같은 '이벤트 핸들러' 안에서는 사용할 수 없답니다. 이벤트 핸들러 안에서는 대신 useRouter 훅(hook)을 사용하셔야 해요.
  • redirecthttps://... 로 시작하는 절대 URL(Absolute URLs)도 받을 수 있기 때문에, 외부 링크로 튕겨내야 할 때도 사용할 수 있어요.
  • 만약 리액트의 렌더링 프로세스가 시작되기도 전에 아예 먼저 리다이렉트를 시켜버리고 싶다면, next.config.js 설정이나 Proxy(프록시)를 사용하시는 게 맞습니다.

📘 강사의 부연 설명: 서버 액션에서 게시글을 작성한 뒤 redirecttry 안에서 쓰면 안 된다는 거, 실무에서 정말 많이 하는 실수예요! 꼭 명심해 주세요. 더 자세한 내용은 redirect API 레퍼런스를 참고해 보세요.


permanentRedirect 함수

permanentRedirect 함수는 사용자를 다른 URL로 영구적으로(permanently) 이동시킬 때 사용합니다. 이 함수 역시 서버 컴포넌트, 라우트 핸들러, 서버 함수에서 호출할 수 있어요.

이 함수는 특정 엔티티의 대표 URL(canonical URL) 자체가 아예 바뀌어버리는 작업 이후에 자주 쓰입니다. 예를 들면, 사용자가 자신의 닉네임(username)을 변경해서 사용자 프로필 URL 자체가 바뀌어야 할 때 말이죠!

//filename="app/actions.ts" switcher
'use server'

import { permanentRedirect } from 'next/navigation'
import { revalidateTag } from 'next/cache'

export async function updateUsername(username: string, formData: FormData) {
  try {
    // Call database
  } catch (error) {
    // Handle errors
  }

  revalidateTag('username') // Update all references to the username
  permanentRedirect(`/profile/${username}`) // Navigate to the new user profile
}
//filename="app/actions.js" switcher
'use server'

import { permanentRedirect } from 'next/navigation'
import { revalidateTag } from 'next/cache'

export async function updateUsername(username, formData) {
  try {
    // Call database
  } catch (error) {
    // Handle errors
  }

  revalidateTag('username') // Update all references to the username
  permanentRedirect(`/profile/${username}`) // Navigate to the new user profile
}

💡 알아두면 좋은 팁 (Good to know):

  • permanentRedirect는 기본적으로 308 (영구 리다이렉트 - permanent redirect) 상태 코드를 반환해요.
  • 이 함수 역시 절대 URL을 허용하므로 외부 링크로 보낼 때 사용할 수 있습니다.
  • 렌더링 프로세스 이전에 리다이렉트 하려면 next.config.jsProxy를 사용하세요.

📘 강사의 SEO 꿀팁: 여러분, 307(임시)과 308(영구)의 차이가 왜 중요한지 아시나요? 검색엔진 최적화(SEO) 때문이에요! 구글 봇(Google Bot) 같은 검색 엔진 크롤러가 308 코드를 만나면 "아, 이 페이지 주소가 아예 이걸로 바뀌었구나! 내 검색 결과 목록(Index)을 업데이트해야지!" 하고 인지하게 됩니다. 주소가 영구적으로 바뀌었다면 꼭 permanentRedirect를 써주세요.
더 자세한 내용은 permanentRedirect API 레퍼런스를 참고하세요.


useRouter() 훅 (hook)

만약 클라이언트 컴포넌트의 '이벤트 핸들러(예: 버튼의 onClick 이벤트)' 안에서 리다이렉트를 시켜야 한다면, useRouter 훅이 제공하는 push 메서드를 사용하시면 됩니다. 한번 볼까요?

//filename="app/page.tsx" switcher
'use client'

import { useRouter } from 'next/navigation'

export default function Page() {
  const router = useRouter()

  return (
    <button type="button" onClick={() => router.push('/dashboard')}>
      Dashboard
    </button>
  )
}
//filename="app/page.js" switcher
'use client'

import { useRouter } from 'next/navigation'

export default function Page() {
  const router = useRouter()

  return (
    <button type="button" onClick={() => router.push('/dashboard')}>
      Dashboard
    </button>
  )
}

💡 알아두면 좋은 팁 (Good to know):

  • 자바스크립트를 통한 프로그래밍 방식의 네비게이션(이동)이 굳이 필요하지 않은 상황이라면, 가급적 <Link> 컴포넌트를 사용하는 것이 훨씬 좋습니다.

📘 강사의 부연 설명: 왜 <Link>를 쓰는 게 더 좋을까요? Next.js의 <Link> 컴포넌트는 화면에 링크가 보일 때 해당 페이지의 데이터를 미리 백그라운드에서 불러오는 프리패칭(Prefetching) 기능을 기본적으로 제공하기 때문이에요! 그래서 사용자가 클릭했을 때 훨씬 빠르게 화면이 전환됩니다. 폼 제출 등 로직 처리 후에 넘어가야 할 때만 useRouter를 쓰시고, 단순 페이지 이동은 무조건 <Link>를 쓰세요. push 외에도 뒤로가기 히스토리를 남기지 않는 replace 메서드도 있으니 유용하게 활용해보세요!
더 궁금하신 점은 useRouter API 레퍼런스에서 확인할 수 있습니다.


next.config.js 파일의 redirects

next.config.js 파일 안의 redirects 옵션을 사용하면 들어오는 요청(Request)의 경로를 아예 다른 목적지 경로로 리다이렉트 시킬 수 있어요. 이건 주로 사이트의 URL 구조를 대대적으로 개편하거나, 사전에 미리 알려진 리다이렉트 목록들이 있을 때 아주 유용하게 쓰인답니다.

redirects 옵션은 단순 경로 매칭 뿐만 아니라 헤더(header), 쿠키(cookie), 쿼리(query) 매칭도 지원해요. 즉, 들어오는 요청의 세부적인 조건에 따라 유연하게 사용자들을 리다이렉트 시킬 수 있다는 뜻이죠.

redirects를 사용하려면 next.config.js 파일에 다음과 같이 옵션을 추가해주면 됩니다.

//filename="next.config.ts" switcher
import type { NextConfig } from 'next'

const nextConfig: NextConfig = {
  async redirects() {
    return [
      // Basic redirect (기본 리다이렉트)
      {
        source: '/about',
        destination: '/',
        permanent: true,
      },
      // Wildcard path matching (와일드카드 경로 매칭)
      {
        source: '/blog/:slug',
        destination: '/news/:slug',
        permanent: true,
      },
    ]
  },
}

export default nextConfig
//filename="next.config.js" switcher
module.exports = {
  async redirects() {
    return [
      // Basic redirect
      {
        source: '/about',
        destination: '/',
        permanent: true,
      },
      // Wildcard path matching
      {
        source: '/blog/:slug',
        destination: '/news/:slug',
        permanent: true,
      },
    ]
  },
}

더 자세한 설정 방법은 redirects API 레퍼런스를 확인해주세요.

💡 알아두면 좋은 팁 (Good to know):

  • redirects 설정에서 permanent 옵션의 값에 따라 307(임시, false일 경우) 또는 308(영구, true일 경우) 상태 코드를 반환하게 됩니다.
  • 배포하는 플랫폼에 따라 redirects 개수에 제한이 있을 수 있어요. 예를 들어 Vercel 같은 플랫폼에서는 1,024개까지만 리다이렉트 규칙을 넣을 수 있답니다. 1,000개가 넘어가는 엄청난 양의 리다이렉트를 관리해야 한다면, Proxy를 활용한 커스텀 솔루션을 구축하는 것을 고려해보세요. 아래의 대규모 리다이렉트 관리하기 섹션에서 자세히 다룹니다.
  • 주의할 점! redirects는 Proxy가 실행되기 이전에 먼저 실행됩니다.

📘 강사의 팁: 이 방식은 앱이 '빌드(build)'되거나 '시작'될 때 설정되는 것이기 때문에, 동적으로 바뀌는 리다이렉트보다는 고정된 레거시 URL 마이그레이션(예: 옛날 쇼핑몰 상품 링크를 새 사이트 링크로 매핑) 등에 쓰기 좋습니다.


Proxy에서의 NextResponse.redirect

Proxy(프록시)를 사용하면 서버에서 요청이 완료되기 전에 특정 코드를 미리 실행해 볼 수 있습니다. 그래서 들어온 요청의 내용(조건)을 검사한 뒤 NextResponse.redirect를 써서 다른 URL로 넘겨버릴 수가 있죠. 이건 사용자의 로그인 여부(인증), 세션 관리 등의 조건부 리다이렉트가 필요하거나, 앞서 말한 엄청나게 많은 양의 리다이렉트 규칙이 있을 때 쓰기 딱 좋은 방법이에요.

예를 들어, 로그인을 하지 않은(인증되지 않은) 사용자를 억지로 /login 페이지로 튕겨내고 싶을 때는 이렇게 작성합니다:

//filename="proxy.ts" switcher
import { NextResponse, NextRequest } from 'next/server'
import { authenticate } from 'auth-provider'

export function proxy(request: NextRequest) {
  const isAuthenticated = authenticate(request)

  // If the user is authenticated, continue as normal
  // 사용자가 인증된 상태라면, 정상적으로 하려던 요청을 계속 진행합니다.
  if (isAuthenticated) {
    return NextResponse.next()
  }

  // Redirect to login page if not authenticated
  // 인증되지 않았다면 로그인 페이지로 리다이렉트 시킵니다.
  return NextResponse.redirect(new URL('/login', request.url))
}

export const config = {
  matcher: '/dashboard/:path*',
}
//filename="proxy.js" switcher
import { NextResponse } from 'next/server'
import { authenticate } from 'auth-provider'

export function proxy(request) {
  const isAuthenticated = authenticate(request)

  // If the user is authenticated, continue as normal
  if (isAuthenticated) {
    return NextResponse.next()
  }

  // Redirect to login page if not authenticated
  return NextResponse.redirect(new URL('/login', request.url))
}

export const config = {
  matcher: '/dashboard/:path*',
}

💡 알아두면 좋은 팁 (Good to know):

  • Proxy는 next.config.js에 있는 redirects 처리가 끝난 이후에, 그리고 실제 페이지가 렌더링 되기 이전에 실행된답니다.

📘 강사의 부연 설명: Next.js 생태계를 오랫동안 보신 분들이라면 "어? 이거 Middleware(미들웨어) 파일이랑 똑같은 역할 아니야?" 라고 생각하실 수 있어요. 맞습니다! 최신 라우팅 규칙 하에서 처리하는 과정으로, 페이지가 그려지기도 전에 서버의 엣지(Edge) 단에서 요청을 가로채서 판별하는 강력한 기능입니다. 라우트 보호(Route Guarding)를 할 때 1순위로 고려해야 할 기술이죠.
자세한 내용은 Proxy 문서를 꼭 확인해보세요!


대규모 리다이렉트 관리하기 (고급)

만약 다뤄야 할 리다이렉트 룰이 1,000개가 넘어갈 정도로 많다면(at scale), Proxy를 이용해 커스텀 솔루션을 만드는 것을 권장합니다. 이 방식을 사용하면, 애플리케이션을 굳이 다시 배포(redeploy)하지 않아도 프로그래밍 방식으로 유연하게 리다이렉트를 관리할 수 있게 되거든요.

이를 구현하려면 다음 두 가지를 고민하셔야 해요.

  1. 리다이렉트 맵(지도)을 만들고 저장하기.
  2. 데이터를 찾아보는(Lookup) 성능 최적화하기.

Next.js 공식 예제: 아래에서 권장하는 내용들을 실제로 구현해 놓은 블룸 필터를 활용한 Proxy (Proxy with Bloom filter) 예제를 참고해 보세요.

1. 리다이렉트 맵 만들고 저장하기

리다이렉트 맵은 쉽게 말해 '어디서 어디로 갈지' 적어둔 목록표입니다. 이걸 데이터베이스(주로 키-값 형태의 저장소)나 JSON 파일로 저장해 둘 수 있어요.

이런 식의 데이터 구조를 생각해 볼 수 있겠죠:

{
  "/old": {
    "destination": "/new",
    "permanent": true
  },
  "/blog/post-old": {
    "destination": "/blog/post-new",
    "permanent": true
  }
}

Proxy 내에서, Vercel의 Edge ConfigRedis 같은 초고속 데이터베이스에서 이 맵을 읽어온 뒤, 사용자의 요청 경로에 맞춰 리다이렉트 시킬 수 있어요.

//filename="proxy.ts" switcher
import { NextResponse, NextRequest } from 'next/server'
import { get } from '@vercel/edge-config'

type RedirectEntry = {
  destination: string
  permanent: boolean
}

export async function proxy(request: NextRequest) {
  const pathname = request.nextUrl.pathname
  const redirectData = await get(pathname)

  if (redirectData && typeof redirectData === 'string') {
    const redirectEntry: RedirectEntry = JSON.parse(redirectData)
    const statusCode = redirectEntry.permanent ? 308 : 307
    return NextResponse.redirect(redirectEntry.destination, statusCode)
  }

  // No redirect found, continue without redirecting
  // 일치하는 리다이렉트 규칙이 없으면 그대로 진행합니다.
  return NextResponse.next()
}
//filename="proxy.js" switcher
import { NextResponse } from 'next/server'
import { get } from '@vercel/edge-config'

export async function proxy(request) {
  const pathname = request.nextUrl.pathname
  const redirectData = await get(pathname)

  if (redirectData) {
    const redirectEntry = JSON.parse(redirectData)
    const statusCode = redirectEntry.permanent ? 308 : 307
    return NextResponse.redirect(redirectEntry.destination, statusCode)
  }

  // No redirect found, continue without redirecting
  return NextResponse.next()
}

2. 데이터 조회(Lookup) 성능 최적화하기

들어오는 '모든' 요청마다 무거운 데이터베이스를 조회하는 건 속도도 느려지고 비용도 많이 드는 일이에요. 이걸 최적화하는 데는 보통 두 가지 방법이 있어요.

  • 읽기 속도가 극도로 빠른 특화된 데이터베이스를 사용하기.
  • 대용량 파일이나 DB를 읽기 전에, 리다이렉트 대상이 존재하는지부터 아주 가볍고 빠르게 검사해 볼 수 있는 블룸 필터(Bloom filter) 같은 조회 전략을 사용하기.

이전 예제에 이어서, 생성된 블룸 필터 파일을 Proxy로 가져온 다음에, 사용자가 요청한 경로(pathname)가 블룸 필터 안에 존재하는지부터 먼저 체크하는 방법을 보여드릴게요.

만약 블룸 필터에 존재한다고 판별되면, 그 요청을 라우트 핸들러(Route Handler) 로 넘깁니다. 그러면 그 라우트 핸들러가 실제 리다이렉트 맵 파일이나 DB를 뒤져서 정확한 목적지 URL로 넘겨주는 방식이에요.
이렇게 하면 Proxy 자체에 무겁고 거대한 리다이렉트 맵 파일을 전부 다 가져오지 않아도 되니까, 일반적인 모든 요청들의 처리 속도가 느려지는 걸 방지할 수 있답니다.

//filename="proxy.ts" switcher
import { NextResponse, NextRequest } from 'next/server'
import { ScalableBloomFilter } from 'bloom-filters'
import GeneratedBloomFilter from './redirects/bloom-filter.json'

type RedirectEntry = {
  destination: string
  permanent: boolean
}

// Initialize bloom filter from a generated JSON file
// 미리 생성해둔 JSON 파일로부터 블룸 필터를 초기화합니다.
const bloomFilter = ScalableBloomFilter.fromJSON(GeneratedBloomFilter as any)

export async function proxy(request: NextRequest) {
  // Get the path for the incoming request
  const pathname = request.nextUrl.pathname

  // Check if the path is in the bloom filter
  // 블룸 필터 안에 이 경로가 있는지 '빠르게' 검사합니다.
  if (bloomFilter.has(pathname)) {
    // Forward the pathname to the Route Handler
    // 존재할 가능성이 있다면, 라우트 핸들러로 요청을 토스합니다.
    const api = new URL(
      `/api/redirects?pathname=${encodeURIComponent(request.nextUrl.pathname)}`,
      request.nextUrl.origin
    )

    try {
      // Fetch redirect data from the Route Handler
      const redirectData = await fetch(api)

      if (redirectData.ok) {
        const redirectEntry: RedirectEntry | undefined =
          await redirectData.json()

        if (redirectEntry) {
          // Determine the status code
          const statusCode = redirectEntry.permanent ? 308 : 307

          // Redirect to the destination
          return NextResponse.redirect(redirectEntry.destination, statusCode)
        }
      }
    } catch (error) {
      console.error(error)
    }
  }

  // No redirect found, continue the request without redirecting
  return NextResponse.next()
}
//filename="proxy.js" switcher
import { NextResponse } from 'next/server'
import { ScalableBloomFilter } from 'bloom-filters'
import GeneratedBloomFilter from './redirects/bloom-filter.json'

// Initialize bloom filter from a generated JSON file
const bloomFilter = ScalableBloomFilter.fromJSON(GeneratedBloomFilter)

export async function proxy(request) {
  // Get the path for the incoming request
  const pathname = request.nextUrl.pathname

  // Check if the path is in the bloom filter
  if (bloomFilter.has(pathname)) {
    // Forward the pathname to the Route Handler
    const api = new URL(
      `/api/redirects?pathname=${encodeURIComponent(request.nextUrl.pathname)}`,
      request.nextUrl.origin
    )

    try {
      // Fetch redirect data from the Route Handler
      const redirectData = await fetch(api)

      if (redirectData.ok) {
        const redirectEntry = await redirectData.json()

        if (redirectEntry) {
          // Determine the status code
          const statusCode = redirectEntry.permanent ? 308 : 307

          // Redirect to the destination
          return NextResponse.redirect(redirectEntry.destination, statusCode)
        }
      }
    } catch (error) {
      console.error(error)
    }
  }

  // No redirect found, continue the request without redirecting
  return NextResponse.next()
}

그리고 이 요청을 넘겨받는 라우트 핸들러 쪽의 코드는 이렇게 생겼습니다.

//filename="app/api/redirects/route.ts" switcher
import { NextRequest, NextResponse } from 'next/server'
import redirects from '@/app/redirects/redirects.json'

type RedirectEntry = {
  destination: string
  permanent: boolean
}

export function GET(request: NextRequest) {
  const pathname = request.nextUrl.searchParams.get('pathname')
  if (!pathname) {
    return new Response('Bad Request', { status: 400 })
  }

  // Get the redirect entry from the redirects.json file
  // redirects.json 파일에서 실제 리다이렉트 정보를 가져옵니다.
  const redirect = (redirects as Record<string, RedirectEntry>)[pathname]

  // Account for bloom filter false positives
  // 블룸 필터의 긍정 오류(False Positive, 있다고 했는데 실제론 없는 경우)를 처리합니다.
  if (!redirect) {
    return new Response('No redirect', { status: 400 })
  }

  // Return the redirect entry
  return NextResponse.json(redirect)
}
import { NextResponse } from 'next/server'
import redirects from '@/app/redirects/redirects.json'

export function GET(request) {
  const pathname = request.nextUrl.searchParams.get('pathname')
  if (!pathname) {
    return new Response('Bad Request', { status: 400 })
  }

  // Get the redirect entry from the redirects.json file
  const redirect = redirects[pathname]

  // Account for bloom filter false positives
  if (!redirect) {
    return new Response('No redirect', { status: 400 })
  }

  // Return the redirect entry
  return NextResponse.json(redirect)
}

💡 알아두면 좋은 팁 (Good to know):

  • 블룸 필터를 생성하려면 bloom-filters 같은 별도의 외부 라이브러리를 사용할 수 있습니다.
  • 악의적인 요청을 방지하기 위해서 라우트 핸들러로 들어오는 요청은 반드시 유효성 검사(Validate)를 해주셔야 해요.

📘 강사의 부연 설명: 블룸 필터라는 개념이 낯설죠? 아주 간단히 비유하자면, 도서관(DB)에 들어가서 책을 샅샅이 뒤지기 전에, 문 앞에 있는 '도서 검색기(블룸 필터)'에 물어보는 거예요. 검색기가 "그 책 우리 도서관에 없어!" 라고 하면 아예 안 들어가면 되니까 시간이 절약되죠. 다만 아주 가끔 검색기가 "어? 있을지도?" 라고 해서 들어가 봤는데 없는 경우(False Positives)가 있을 수 있어서, 핸들러에서 한 번 더 꼼꼼히 체크해 주는 거랍니다. 대규모 서비스 프론트엔드 환경을 구축할 때 이 패턴을 알면 정말 유용해요!


  • redirect
    • redirect 함수에 대한 API 레퍼런스입니다.
  • permanentRedirect
    • permanentRedirect 함수에 대한 API 레퍼런스입니다.
  • proxy.js
    • proxy.js 파일에 대한 API 레퍼런스입니다.
  • redirects
    • Next.js 앱에 redirects를 추가하는 방법입니다.

모든 문서의 시맨틱(의미론적) 개요를 보려면, https://nextjs.org/docs/sitemap.md 를 참고해 주세요.

사용 가능한 전체 문서의 색인(Index)을 보려면, https://nextjs.org/docs/llms.txt 를 참고해 주세요.

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

0개의 댓글