Next.js revalidatePath를 썼는데 캐시가 갱신 안 된 이유
문제 발생
Server Action에서 데이터를 수정한 뒤 revalidatePath("/posts")를 호출했는데, 상세 페이지(/posts/[slug])는 여전히 이전 데이터를 보여주는 경우가 있었습니다.
"use server";
export async function updatePost(id: number, data: PostInput) {
await db.update(posts).set(data).where(eq(posts.id, id));
revalidatePath("/posts"); // 목록만 갱신, 상세 페이지는 그대로
}원인 분석
revalidatePath(path)는 정확히 그 경로 세그먼트(및 필요하면 layout/page 타입 지정에 따른 하위 경로)의 캐시를 무효화합니다. /posts를 무효화해도 /posts/[slug]라는 별도의 동적 라우트는 자동으로 함께 무효화되지 않습니다. 두 라우트가 같은 데이터를 보여주더라도 Next.js 입장에서는 서로 다른 경로이기 때문입니다.
revalidateTag(tag)는 이와 다르게 데이터 소스 단위로 무효화합니다. fetch()나 "use cache" 함수에 태그를 붙여두면, 그 태그가 붙은 데이터를 사용하는 모든 경로가 한 번에 무효화됩니다 — 몇 개의 페이지에서 그 데이터를 쓰는지 일일이 알 필요가 없습니다.
해결 방안
- 여러 경로가 같은 데이터에 의존한다면
revalidatePath를 여러 번 호출하기보다 태그 기반으로 설계합니다.
// 데이터를 가져오는 곳에서 태그를 붙인다
async function getPost(id: number) {
"use cache";
cacheTag(`post-${id}`);
return db.query.posts.findFirst({ where: eq(posts.id, id) });
}
// 수정하는 곳에서 그 태그만 무효화하면 목록/상세 모두 갱신됨
revalidateTag(`post-${id}`, "max"); // 두 번째 인자로 cacheLife 프로필 명시revalidatePath는 정말로 "이 경로 하나만 다시 렌더링하면 된다"는 게 명확할 때만 씁니다 — 예를 들어 목록 페이지 하나만 영향받는 변경.- Server Action에서 read-your-writes(수정 직후 최신 데이터를 바로 보여줘야 하는 경우)가 필요하면
updateTag()를 씁니다 —revalidateTag는 다음 요청부터 반영되지만, 같은 요청 흐름 안에서 즉시 최신값을 읽어야 하는 경우를 위한 별도 API입니다. - 변경한 데이터가 어느 경로들에 영향을 주는지 명확하지 않다면, 우선 관련된 상위
layout경로까지 포함해 무효화 범위를 넓게 잡고, 이후 태그 기반으로 점진적으로 세밀화하는 편이 안전합니다.
공식 문서
캐싱 관련 API는 Next.js 버전마다 변화가 빠른 영역이므로 실제 설치된 버전의 문서를 반드시 확인합니다.
댓글0
댓글을 남기려면 로그인이 필요해요. 로그인
아직 댓글이 없어요. 첫 의견을 편하게 남겨 보세요.