Skip to content

Latest commit

 

History

History
204 lines (157 loc) · 6.81 KB

리다이렉트.md

File metadata and controls

204 lines (157 loc) · 6.81 KB

리다이렉트

API 목적 어디서 상태코드
redirect 이벤트 또는 변화가 생겼을때 유저를 리다이렉트 시킴 서버 컴포넌트, 서버 액션, 라우팅 핸들러 307 or 303
permannentRedirect 이벤트 또는 변화가 생겼을때 유저를 리다이렉트 시킴 서버 컴포넌트, 서버 액션, 라우팅 핸들러 308
useRouter 클라이언트 사이드에서 이동 클라이언트 컴포넌트에서 이벤트 핸들러 -
redirects in next.config.mjs 특정 경로에 대한 request 요청을 리다이렉트 next.config.mjs 파일 307 or 308
NextResponse.redirect 특정 조건에 따라서 request 요청을 리다이렉트 미들웨어 아무거나

redirect 함수

  • 유저를 다른 URL로 이동시킬때 사용함
  • 서버컴포넌트, 서버액션, 라우트 핸들러에서 사용이 가능함
  • 보통 이벤트 또는 변화가 생겼을때 사용함
  • 클라이언트 컴포넌트에서도 사용이 가능하지만 이벤트 핸들러 내부에선 불가능함
"use server";

import { redirect } from "next/navigation";
import { revalidatePath } from "next/cache";

export async function createPost(id: string) {
  try {
    // 데이터베이스 호출
  } catch (error) {
    // 에러 핸들링
  }

  revalidatePath("/posts"); // 캐싱되어있는 게시글 목록 업데이트
  redirect(`/post/${id}`); // 새로운 게시글 페이지로 이동
}

permanentRedirect 함수

  • 보통 영구적으로 다른 URL로 이동시키기 위해서 사용함
  • 서버컴포넌트, 서버액션, 라우트 핸들러에서 사용이 가능함
  • 엔티티의 표준 URL을 변경할때 등 변화 또는 이벤트 이후에 주로 사용함
    • 예를 들어서 유저가 이름을 변경하면 업데이트된 URL로 이동시킬때 사용
"use server";

import { permanentRedirect } from "next/navigation";
import { revalidateTag } from "next/cache";

export async function updateUsername(username: string, formData: FormData) {
  try {
    // DB 호출
  } catch (error) {
    // 에러 핸들링
  }

  revalidateTag("username"); // 모든 username에 대한 캐시를 갱신
  permanentRedirect(`/profile/${username}`); // 새로운 유저 페이지로 이동
}

useRouter()

  • 클라이언트 컴포넌트에서 이벤트 핸들러 내부에서 리다이렉트가 필요할떄 사용
  • useRouter().push('url') 메소드를 통해서 사용이 가능함
  • 프로그래밍적으로 유저를 다른곳으로 이동시키는게 아니라면 <Link>를 쓰는것을 권장
"use client";

import { useRouter } from "next/navigation";

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

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

next.config.mjs에서 redirects

  • next.config.mjs에서 redirects 옵션을 사용해서 특정 경로에 대한 요청을 다른곳으로 리다이렉트 시킬 수 있음
  • 페이지를 리팩토링하면서 기존 사용자들이 특정 경로에 왔을때 새로운 페이지로 자동으로 이동하도록 설정할 수 있음
  • path, header, cookie 등 다양한 옵션을 통해서 유연하게 기능을 제공함
  • vercel 호스팅 기준 1024개로 제한이 되어있음
  • 더 많은 리다이렉트를 사용하기 위해서는 middleware를 사용하는것을 고려해야함
module.exports = {
  async redirects() {
    return [
      // 기본 리다이렉트
      {
        source: "/about",
        destination: "/",
        permanent: true,
      },
      // 와일드카드 경로 매칭 리다이렉트
      {
        source: "/blog/:slug",
        destination: "/news/:slug",
        permanent: true,
      },
    ];
  },
};

미들웨어에서 NextReponse.redirect

  • 미들웨어를 사용하면 request가 완료되기 전에 코드 실행이 가능함
  • NextRepsonse.redirect를 통해서 원하는 URL로 리다이렉트를 시킬수 있음
  • 인증, 세션 등 조건에 기반하거나 많은 수의 리다이렉트가 필요할 때 유용함
  • 동작순서는 next.config.mjs가 먼저 수행되고 나서 페이지 렌더링 전에 실행됨
  • 아래는 비인증 유저에 대한 리다이렉트 예시임
import { NextResponse, NextRequest } from "next/server";
import { authenticate } from "auth-provider";

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

  // 인증된 유저라면, 다음 절차를 그대로 진행함
  if (isAuthenticated) {
    return NextResponse.next();
  }

  // 인증되지 않은 유저라면 /login 페이지로 redirect 시킴
  return NextResponse.redirect(new URL("/login", request.url));
}

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

많은 양의 리다이렉트 관리하기 (고급기능)

  • 1000개가 넘어가는 리다이렉트를 관리하기 위해서는 커스텀 미들웨어가 필요함
  • 배포를 다시 안해도 리다이렉트를 동적으로 처리할 수 있음

방법

  1. NoSQL과 같은 key-value 기반 DB나 JSON 파일을 활용해서 redirect map을 구성함
{
  "/old": {
    "destination": "/new",
    "permanent": true
  },
  "/blog/post-old": {
    "destination": "/blog/post-new",
    "permanent": true
  }
}
import { NextResponse, NextRequest } from "next/server";
import { get } from "@vercel/edge-config";

type RedirectEntry = {
  destination: string;
  permanent: boolean;
};

export async function middleware(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);
  }

  // 리다이렉트 구성이 없다면, 다음 단계를 진행함(렌더링 등)
  return NextResponse.next();
}
  1. 데이터 조회 퍼포먼스 개선하기
  • 많은 양의 데이터셋을 매번 읽어오는건 매우 느리고 비용이 비쌈
  • 이를 개선하기 위한 2가지 방법이 존재함
    1. 읽기 요청이 빠른 DB(Redis, Edge Config 등) 사용하기
    2. 읽기 전략(Bloom Filter 등)을 활용한 외부 데이터 조회속도 높이기