Next.js App Router는 기본적으로 서버 컴포넌트에서 GET 요청으로 받아온 데이터를 영구 캐싱합니다. 이후 동일한 요청을 보낼 경우 캐싱된 데이터를 사용하기 때문에 서버 비용을 절약할 수 있습니다.
하지만 데이터 변동이 자주 발생해 최신화가 중요한 상황에서는 캐싱된 데이터와 최신 데이터 간 싱크가 맞지 않아 사용자에게 혼란을 야기할 수 있습니다. 예를 들어 Trablock에서는 다음과 같은 상황이 존재합니다.
<aside>
A)을 조회한다. [A 캐싱 | 서버 최신 데이터 = A]A’)한다. [서버 최신 데이터 = A’]A 사용]
</aside>위 상황에서 작성자가 수정된 여행 계획을 다시 조회했을 때, 작성자가 알고 있는 데이터 A’와 캐싱된 데이터 A가 서로 다르기 때문에 수정이 되지 않은 것으로 인식할 수 있습니다.
Next.js는 캐시를 제어하기 위해 태그 기반 시스템을 사용합니다.
<aside>
tags: 캐시의 태그를 설정합니다.fetch(`https://...`, { next: { tags: ['tag1', 'tag2'] } });
revalidate: 캐시의 수명을 설정합니다.fetch(`https://...`, { next: { revalidate: false | 0 | number } });
revalidateTag: 특정 태그를 가진 캐시를 재검증합니다.import { revalidateTag } from 'next/cache';
revalidateTag('tag1');
</aside>
Trablock에서는 Fetch API에 다음과 같이 적용했습니다.
// 공통 태그
const CACHE_TAGS_PREFIX = {
ARTICLE: 'ARTICLE',
ARTICLE_SCHEDULE: 'ARTICLE_SCHEDULE',
USER_PROFILE: 'USER_PROFILE',
GOOGLE_PLACES: 'GOOGLE_PLACES'
};
// [공통 태그, 고유 태그]
const CACHE_TAGS = {
ARTICLE: {
getArticle: (articleId: number) => [CACHE_TAGS_PREFIX.ARTICLE, `getArticle-${articleId}`],
// ...
};
공통 태그: 같은 카테고리 안에 속한 API에는 동일한 태그를 부여합니다. 동일한 공통 태그를 가진 모든 API에 대해 한번에 재검증할 수 있습니다.
고유 태그: 각 API에 대해 고유한 태그를 부여합니다. 만약 articleId처럼 동적 파라미터가 있을 경우, 해당 파라미터를 반영하여 태그를 생성합니다.