[Next.js] POST 이후 자동으로 화면에 데이터 반영하기

chaen·2025년 2월 17일

REACT / NEXT.js

목록 보기
17/22
post-thumbnail

📌 문제 상황

보통 폼을 제출한 후 강제로 새로고침(window.location.reload())을 해야 변경된 데이터를 확인할 수 있습니다. 하지만 Next.js의 revalidateTag 또는 revalidatePath를 사용하면 새로고침 없이도 자동으로 변경된 데이터를 화면에 반영할 수 있습니다.

이 글에서는 Next.js의 서버 액션(Server Action)을 사용하여 리뷰를 제출한 후, 자동으로 리뷰 목록을 업데이트하는 방법을 설명하겠습니다.


💻 코드 예제

📍 1. 리뷰 작성 폼 (ReviewEditor.tsx)

'use client';

export default function ReviewEditor({ bookId }: { bookId: string }) {
  return (
    <form action={createReviewAction}>
      <input name="bookId" value={bookId} hidden readOnly />
      <textarea name="content" required placeholder="리뷰 내용을 입력하세요." />
      <button type="submit">제출</button>
    </form>
  );
}

✔ 사용자가 폼을 입력하고 제출하면 createReviewAction이 실행됩니다.


📍 2. 리뷰 저장 및 데이터 갱신 (create-review-action.ts)

'use server';

import { revalidateTag } from 'next/cache';

export async function createReviewAction(formData: FormData) {
  const bookId = formData.get('bookId')?.toString();
  const content = formData.get('content')?.toString();

  if (!content) return;

  try {
    await fetch(`${process.env.NEXT_PUBLIC_SERVER_API_URL}/review`, {
      method: 'POST',
      body: JSON.stringify({ bookId, content }),
    });

    // ✅ 해당 리뷰 데이터만 재검증하여 새로고침 없이 자동 반영
    revalidateTag(`review-${bookId}`);
  } catch (err) {
    console.error(err);
  }
}

✔ revalidateTag(\review-${bookId}`)`를 호출하면, 해당 태그와 연결된 데이터만 새로고침 없이 자동으로 갱신됩니다. (자세히 후술)


📍 3. 리뷰 목록 표시 (ReviewList.tsx)

export default async function ReviewList({ bookId }: { bookId: string }) {
  const response = await fetch(
    `${process.env.NEXT_PUBLIC_SERVER_API_URL}/review/book/${bookId}`,
    { next: { tags: [`review-${bookId}`] } }
  );

  if (!response.ok) {
    throw new Error(`리뷰 가져오기 실패: ${response.statusText}`);
  }

  const reviews = await response.json();

  return (
    <section>
      {reviews.map((review) => (
        <div key={review.id}>
          <strong>{review.author}</strong>
          <p>{review.content}</p>
        </div>
      ))}
    </section>
  );
}

✔ fetch() 요청 시 { next: { tags: [\review-${bookId}`] } }`를 추가하면 해당 태그를 가진 데이터가 변경될 때 자동으로 다시 불러옵니다.


📣 다양한 revalidate 활용 방법

✅ 1. 특정 페이지 전체를 재검증 (revalidatePath)

import { revalidatePath } from 'next/cache';
revalidatePath(`/book/${bookId}`);

✔ 해당 페이지를 다시 생성하여 갱신합니다.
✔ 하지만 해당 페이지에 캐싱해둔 다른 데이터도 함께 사라지는 문제가 발생할 수 있습니다.

✅ 2. 특정 경로의 모든 동적 페이지 재검증

revalidatePath("/book/[id]", "page");

✔ /book/1, /book/2, /book/3 등 book 폴더의 [id].tsx로 접속 가능한 모든 페이지 데이터를 갱신합니다.

✅ 3. 특정 레이아웃을 사용하는 모든 페이지 재검증

revalidatePath("/(with-searchbar)", "layout");

✔ /(with-searchbar) 폴더 내의 layout.tsx가 적용되는 모든 페이지가 새로 생성됩니다.

✅ 4. 전체 데이터 재검증 (모든 캐시 삭제)

revalidatePath("", "layout");

✔ 전체 데이터를 재검증하여 모든 캐시를 갱신합니다.. (일반적으로 사용 X)

✅ 5. 특정 데이터 캐시만 재검증 (revalidateTag)

const response = await fetch('path'), {next: {tags: [`review-${id}`]}};
revalidateTag(`review-${bookId}`);

✔ 특정 태그와 연결된 데이터만 갱신 (가장 효율적인 방법!)


🎯 결론

✅ Next.js의 revalidateTag를 활용하면 변경된 데이터를 바로 화면에 렌더링할 수 있음.
✅ 전체 페이지를 다시 불러오지 않고 필요한 데이터만 갱신하므로 성능이 향상됨.
✅ 상황에 따라 revalidatePath와 revalidateTag를 적절히 조합하면 더 효과적인 데이터 갱신이 가능.
✅ 단, pull route를 삭제할 뿐 새롭게 생성하지는 않음. 다음 차례의 접속 요청이 들어오면 그제서야 생성함 -> 가장 최신 데이터를 보여주기 위해!


참고: 한 입 크기로 잘라먹는 Next.js(v15)

0개의 댓글