본문 바로가기
Next.js

revalidatePath();

by ihateindex 2024. 3. 4.

revalidatePath()는 Next.js에서 제공하는 캐시 관련 함수입니다. 해당 함수에 넘겨진 페이지의 캐시를 재검증하여 페이지의 변경된 부분만 새로고침 없이 업데이트합니다.

 

Next.js에서는 서버 컴포넌트 페이지와 클라이언트 컴포넌트 페이지가 있습니다. 클라이언트 페이지에서는 useState를 이용해 변경된 상태를 페이지에 바로바로 재렌더링할 수 있지만, 서버 컴포넌트인 SSR과 SSG는 초기에 한번 렌더링되고 난 후 재렌더링이 되지않습니다.

 

이때 서버 컴포넌트에 새로고침 없이 변경된 부분을 적용해야할때(새로운 컨텐츠를 추가한 뒤, 서버 컴포넌트 페이지에서 모든 컨텐츠들을 다시 로드 해야할때) revalidatePath()가 사용됩니다.

 

서버 컴포넌트는 클라이언트 컴포넌트에서 사용하는 useState를 사용할 수 없어 변경된 부분이 있더라도 다시 렌더링이 되지않기 때문에

revalidatePath()를 사용하여 해당 페이지를 재검증해줍니다.

 

revalidatePath(path: string, type?: 'page' | 'layout'): void;

 

revalidatePath는 첫번째 파라미터로 page path를 받고, 두번째 파라미터로 type을 받습니다. 두번째 파라미터는 선택사항으로써, 첫번째 파라미터인  path만 입력하더라도 동작합니다.

 

하지만, 첫번째 파라미터만 입력시 해당 path만 재검증하고 중첩된 path들은 검증하지 않습니다.

 

revalidatePath('/meals');

meals 페이지만 재검증합니다.

 

두번째 파라미터인 타입을 입력하지 않으면 기본값으로 'page'가 적용됩니다. 'page'는 해당 페이지만 재검증하겠다는 것입니다.

다른 타입인 'layout'은 Next.js에서 사용하는 layout.js가 page.js들을 감싸고 있는 것처럼 해당 path와 관련된 모든 path들, 즉 동적인 path와 중첩 path들까지 모두 재검증한다는 뜻입니다.

 

revalidatePath('/meals', 'layout');

meals 페이지와 meals 페이지와 관련된 모든 페이지를 재검증합니다. (예: meals/share/, meals/[mealSlug])

 

 

전체 페이지를 재검증하려면 path에 루트 경로를 넣고, type을 레이아웃으로 선언합니다.

revalidatePath('/', 'layout');

 

예를들어 Share Meal 페이지라는 페이지는 form으로 이루어진 페이지입니다.

이 페이지는 form에 작성된 Meal 데이터를 서버에 전송합니다.

 

그리고 서버에 저장된 모든 Meal들의 데이터를 서버에서 받아와 화면에 표시하는 Meals 페이지가 있죠.

 

하지만 Share Meal 페이지의 form에서 작성된 Meal 데이터가 서버에 성공적으로 저장되더라도, 전체 Meal 데이터를 표시하는 Meals 페이지에는 표시되지 않습니다. 이는 Meals 페이지가 서버 컴포넌트 페이지이기때문에 사용자가 새로고침하지않는 이상 페이지를 재렌더링하지 않기 때문입니다.

'use server';
import { redirect } from 'next/navigation';
import { saveMeal } from './meals';
import { revalidatePath } from 'next/cache';

export async function shareMeal(previousState, formData) {
    function inInvalidText(text) {
        return !text || text.trim() === '';
    }

    const meal = {
        title: formData.get('title'),
        summary: formData.get('summary'),
        instructions: formData.get('instructions'),
        image: formData.get('image'),
        creator: formData.get('name'),
        creator_email: formData.get('email'),
    };

    if (
        inInvalidText(meal.title) ||
        inInvalidText(meal.summary) ||
        inInvalidText(meal.instructions) ||
        inInvalidText(meal.creator) ||
        inInvalidText(meal.creator_email) ||
        !meal.creator_email.includes('@') ||
        !meal.image ||
        meal.image.size === 0
    ) {
        return {
            message: 'Invalid input.',
        };
    }
    await saveMeal(meal); // saveMeal 함수가 실행되어 meal 데이터가 저장
    revalidatePath('/meals'); // '/meals' 페이지를 재검증해 새로 저장된 meal 데이터를 적용
    redirect('/meals'); // 새로운 meal 데이터가 적용된 '/meals' 페이지로 리다이렉트
}

 

이때 Share Meal 페이지에서 서버로 Meal 데이터가 전송되고 성공적으로 저장되었다는 Response가 왔을 때, revalidatePath()와 redirect()를 이용하여 Meals 페이지를 재검증 및 리다이렉트를 하게되면 새로고침 없이 서버 컴포넌트인 Meals 페이지에 새로운 Meal에 대한 데이터를 새로고침 없이 불러 올 수 있게됩니다.