💢 발생한 문제

`"use client"`를 사용하는 컴포넌트에서, 데이터를 서버에 POST 하고 나서, 데이터들이 리스트형태로 되돌아가는 과정에서 최신 데이터가 반영되게 하려면 어떻게 해야할까??

 

Next.js 공식문서는 다음과 같은 상황에 2가지 해결책을 제시한다.

Cached data can be revalidated in two ways

[Time-based revalidation]
Automatically revalidate data after a certain amount of time has passed.
This is useful for data that changes infrequently and freshness is not as critical.

[On-demand revalidation]
Manually revalidate data based on an event (e.g. form submission). On-demand revalidation can use a tag-based or path-based approach to revalidate groups of data at once. This is useful when you want to ensure the latest data is shown as soon as possible (e.g. when content from your headless CMS is updated).

 

Time-based revalidation은 일정 시간마다 캐싱된 값들을 다시 만들도록 하는 것이다.

처음에 이렇게 만들었다가, 클라이언트분께서 Form을 작성한 이후에 다른 탭을 갔다 와야 저장이 된다고 해결해달라고 하셨다. 

개발자가 아닌 분들에게 하나하나 설명드릴 필요도 없고, 그분들도 알 필요 없다고 생각한다.

그래서, 이를 근본적으로 해결하는 방법으로 On-demand revalidation을 사용하기로 했다.

 

 

✏️ First Solution

1. server component fetch function에 revalidate tag를 달아준다.

const fetchData = async (): Promise<{
  data: NoticeType[];
  totalPages: number;
}> => {
  try {
    const res = await fetch(`${baseUrl}/api/getNotice`, {
      next: { tags: ["notice"] }, // Revalidate Tag
    });

    const { data, totalPages } = await res.json();

    return { data: data, totalPages: totalPages };
  } catch (error) {
    console.log(error);
  }
  return { data: [], totalPages: 0 };
};

 

2. Form을 제출하는 Client 컴포넌트에 `"next/cahce"`에서의 `revalidateTag` 함수를 실행시킨다.

  // Form Submit
  const submitHandler = async (isImp: boolean): Promise<undefined> => {
    try {
      // 데이터 만들기
      const data: NoticeType = {
        ...noticeInput,
        contents: contents,
        timeStamp: new Date(),
        important: isImp,
      };
      setNotices(data);      
      
      customRevalidateTag("notice"); // On-Demand revalidation
      
      const nextPath: Path = "/notification?page=1";
      router.push(nextPath);
    } catch (error) {
      console.log("Error Occured on Submitting!", error);
    }
  };

 

💢 Problem

하지만, 문제가 발생했다. revalidateTag는 서버에서 실행하는 코드이므로, "use client"를 사용한 컴포넌트 즉, Form이 있는 컴포넌트에서는 사용할 수 없다.

 

그래서, `revalidateTag`만 사용하는 함수를 분리하고, `import`하여 사용하였다.

 

최종 Solution

// customRevaliateTag.ts
"use server";
import { revalidateTag } from "next/cache";

export async function customRevalidateTag(tag: string) {
  console.log("revalidating");

  revalidateTag(tag);
}
// Form Component

  const submitHandler = async (isImp: boolean): Promise<undefined> => {
    try {
      const data: NoticeType = {
        ...noticeInput,
        contents: contents,
        timeStamp: new Date(),
        important: isImp,
      };
      setNotices(data);      
      
      customRevalidateTag("notice"); // 새로 만든 On-Demand Function
      
      const nextPath: Path = "/notification?page=1";
      router.push(nextPath);
    } catch (error) {
      console.log("Error Occured on Submitting!", error);
    }
  };

 

참고

추가로, 나는 build해서 실행했을때, `revalidate`을 통해 Caching을 다시하는 와중에 `router.push`가 되는 것을 방지하고자, `setTimeout`을 실행시켜주었다.

이때, async Function안에서 setTimeout을 연속적으로 실행시키기 위해 새로 함수를 정의하여서 사용하였다.

 

해당 함수를 이 글을 참고해주세요.

2024.04.30 - [웹 프로그래밍/JavaScript] - async, await + setTimeout 동시에 사용하기

const submitHandler = async (isImp: boolean): Promise<undefined> => {
    try {
      const data: NoticeType = {
        ...noticeInput,
        contents: contents,
        timeStamp: new Date(),
        important: isImp,
      };
      setNotices(data);
      
      setIsSaving(true); // 저장 중임을 표시하기 위해
      customRevalidateTag("notice");
      await delayTimeout(4000); // Promise Timer 함수
      
      const nextPath: Path = "/notification?page=1";
      router.push(nextPath);
    } catch (error) {
      console.log("Error Occured on Submitting!", error);
    }
  };

 

 

참고자료

https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating

 

Data Fetching: Fetching, Caching, and Revalidating | Next.js

Learn how to fetch, cache, and revalidate data in your Next.js application.

nextjs.org

https://github.com/vercel/next.js/discussions/58600

 

'웹 프로그래밍 > Next.js' 카테고리의 다른 글

[Next.js] CSR, SSG, SSR 제대로 알자  (4) 2024.03.24

+ Recent posts