[TIL] 241113_Next.js: Revalidate - Day17

지코·2024년 11월 13일
0

Today I Learned

목록 보기
53/66
post-thumbnail
export default function Page() {
	return (
		<h1>리뷰 재검증 구현하기 🤓</h1>
    );
}

⚡️ 리뷰 재검증 구현하기

지난 포스트까지 진행한 프로젝트 결과물을 보면, 사용자가 리뷰를 등록하고 그 리뷰를 하단에서 확인하기 위해서는 추가적으로 새로고침을 눌러줘야 하는 상태이다.

따라서 Revalidate 를 적용하여, 새로고침을 하지 않더라도 추가된 리뷰를 바로 확인할 수 있도록 구현하려고 한다.

📁 src/actions/create-review.action.ts

"use server";

import { revalidatePath } from "next/cache";

export async function createReviewAction<(formData: FormData) {
  // 데이터 꺼내 쓰기
  const bookId = formData.get("bookId")?.toString();
  const content = formData.get("content")?.toString();
  const author = formData.get("author")?.toString();
  // 예외 처리
  if (!bookId || !content || !author) {
    return;
  }
  // 리뷰 추가 기능 구현
  try {
    // api 경로, fetch 요청의 옵션 객체
    const response = await fetch(
      `${process.env.NEXT_PUBLIC_API_SERVER_URL}/review`, {
        method: "POST",
        body: JSON.stringify({ bookId, content, author }),
      }
    );

    console.log(response.status);
    revalidatePath(`/book/${bookId}`);
  } catch(err) {
    console.error(err);
    return;
  }
}

리뷰 작성 섹션에서 작성하기 버튼을 누르면 실행되는 함수인 createReviewAction() 함수에 위와 같이 revalidate 를 적용한다.

revalidatePath() 함수를 불러와, 데이터가 넘어왔을 때 해당 경로에 대한 페이지를 재생성할 수 있도록 한다.

📁 src/app/book/[id]/page.tsx

export default function Page({
  params,
}: {
  params: { id: string };
}) {
  return (
    <div className={style.container}>
      <BookDetail bookId={params.id} />
      <ReviewEditor bookId={params.id} />
      <ReviewList bookId={params.id} />
    </div>
  );
}

이 때 revalidate 를 적용하고 새로고침하면, 해당 함수를 사용하는 ReviewEditor 컴포넌트 뿐만 아니라 Page 컴포넌트 자체가 리렌더링된다.

그럼 Page 컴포넌트 안에 포함된 BookDetail, ReviewList 컴포넌트 모두 리렌더링되며, 컴포넌트가 가진 fetch 함수에 의해 데이터 페칭도 다시 수행된다.

그렇게 재생성된 페이지를 브라우저에게 전달해주면 클라이언트 측에서는 전달 받은 데이터로 페이지를 리렌더링해서 새로운 리뷰를 바로 확인할 수 있게 한다.


⚠️ revalidatePath() 사용 시 주의할 점

1️⃣ revalidatePath() 함수는 서버 측에서만 호출할 수 있는 메서드이기 때문에, 서버 컴포넌트에서 사용하거나 서버 액션 내부에서 호출하기만 할 수 있다.

2️⃣ revalidatePath() 함수는 인수로 받은 경로에 대한 페이지를 모두 재검증하는 함수이기 때문에, 페이지에 포함된 캐시들까지도 모두 무효화시킨다.

그 캐시에는 캐시 옵션 설정을 통해 생성되는 데이터 캐시만 포함된 것이 아니라, 페이지 전체를 캐싱하는 풀 라우트 캐시 또한 포함된다.
특히 풀 라우트 캐시는 revalidatePath() 함수 실행 시 무효화되며, 리뷰 추가를 통해 새롭게 생성된 페이지를 풀 라우트 캐시에 자동으로 저장해주지는 않는다.
새로 고침을 통해 같은 페이지에 재접속하면 서버는 페이지를 새롭게 생성하며, 그 때는 업데이트된 풀 라우트 캐시를 확인할 수 있다.

정리

먼저 book/1 경로로 접속하면 도서 정보, 리뷰 정보 데이터를 백엔드 서버로부터 불러와 각각 데이터 캐시로 저장한다. 이 과정을 통해 페이지가 완성되면 페이지 전체 데이터를 풀 라우트 캐시로 저장한다.

여기서 revalidatePath() 함수를 사용하면 저장되어 있던 풀 라우트 캐시와 데이터 캐시 모두 무효화가 되며, 데이터 페칭 시 백엔드 서버로부터 불러와 데이터 캐시를 갱신한다. 그리고 새롭게 만든 페이지를 브라우저에게 응답해주게 된다. 이 때 풀 라우트 캐시는 갱신되지 않는다.

같은 book/1 경로로 접속 요청이 들어오면 실시간으로 페이지를 재생성해서 풀 라우트 캐시에 저장한다.

이렇게 동작하는 이유는 최신의 데이터를 보장하기 위해서‼️‼️‼️


Reference

👩🏻‍🏫 한입 크기로 잘라 먹는 Next.js(15+) https://www.inflearn.com/course/한입-크기-nextjs/

profile
꾸준하고 성실하게, FE 개발자 역량을 키워보자 !

0개의 댓글