본문 바로가기
기술, 개발/nextjs

7차 강의 노트 (페이지 캐싱)

by Jaejin Sim 2025. 8. 28.
반응형

1. Full Route Cache (풀 라우트 캐시)

개념

  • Next.js 서버에서 빌드 타임에 특정 페이지의 렌더링 결과를 캐싱하는 기능
  • **SSG(Static Site Generation)**와 거의 동일한 개념
  • 정적으로 렌더링된 페이지를 메모리에 저장하여 빠른 응답 제공

적용 조건

풀 라우트 캐시는 Static Page에만 적용됩니다.

Static Page 기준

  • Dynamic Page가 아닌 모든 페이지
  • 빌드 타임에 내용이 결정될 수 있는 페이지

Dynamic Page 기준 (다음 중 하나라도 해당)

  • 요청마다 변화가 생기거나 데이터가 변경되는 페이지
  • 동적 함수 사용: cookies(), headers(), searchParams 등
  • fetch() 설정이 no-store이거나 캐시 옵션이 없는 경우
  • Suspense로 감싸진 비동기 컴포넌트가 있는 경우

Revalidation (재검증)

// ISR과 유사한 동작
export const revalidate = 3; // 3초 후 stale 상태가 되면 백그라운드에서 재생성

// 또는 fetch 레벨에서 설정
await fetch('/api/data', {
  next: { revalidate: 3 }
});

  • 설정된 시간이 지나면 캐시가 stale 상태가 됨
  • 다음 요청 시 캐시된 내용을 먼저 제공하고, 백그라운드에서 새로운 버전 생성
  • 생성 완료 후 캐시 업데이트

2. 동적 페이지 처리

일반적인 Dynamic Page 예시

  • 검색 페이지: 쿼리 파라미터에 따라 결과가 달라짐
  • 쿠키 기반 개인화: 사용자별 다른 내용 표시
  • 실시간 데이터: 매 요청마다 최신 정보 필요

useSearchParams와 Suspense 패턴

import { Suspense } from 'react';
import { useSearchParams } from 'next/navigation';

// useSearchParams를 사용하는 컴포넌트는 Suspense로 감싸야 함
function SearchComponent() {
  const searchParams = useSearchParams();
  const query = searchParams.get('q');

  return <div>검색어: {query}</div>;
}

export default function SearchPage() {
  return (
    <div>
      <h1>검색 페이지</h1>
      <Suspense fallback={<div>로딩 중...</div>}>
        <SearchComponent />
      </Suspense>
    </div>
  );
}

중요: useSearchParams를 사용하는 컴포넌트를 Suspense로 감싸지 않으면 빌드 시 전체 페이지가 동적으로 처리됩니다.

3. generateStaticParams와 Dynamic Routes

기본 사용법

// app/book/[id]/page.tsx

export const dynamicParams = false; // false 설정 시, 정의되지 않은 id는 404

export function generateStaticParams() {
  return [
    { id: "1" },
    { id: "2" },
    { id: "3" }
  ];
}

export default async function BookPage({ params }: { params: { id: string } }) {
  // generateStaticParams가 있으면 fetch 결과가 자동으로 캐싱됨
  const response = await fetch(
    `${process.env.NEXT_PUBLIC_API_SERVER_URL}/book/${params.id}`
  );

  if (!response.ok) {
    if (response.status === 404) {
      notFound();
    }
    return <div>오류가 발생했습니다.</div>;
  }

  const book = await response.json();
  return <div>{book.title}</div>;
}

dynamicParams 옵션

  • true (기본값): 정의되지 않은 파라미터도 허용, 런타임에 생성
  • false: 정의된 파라미터만 허용, 나머지는 404

4. Route Segment Config Options

dynamic 옵션

export const dynamic = "force-dynamic";

설정값들

  • auto (기본값): Next.js가 자동으로 판단
  • force-dynamic: 페이지를 강제로 Dynamic으로 설정
  • force-static: 페이지를 강제로 Static으로 설정 (주의: 동적 기능 동작 안 할 수 있음)
  • error: Static으로 설정하되, 동적 요소 발견 시 빌드 에러

권장사항: 특별한 상황이 아니라면 사용하지 않는 것을 권장합니다.

기타 Route Segment Options

export const revalidate = 60;           // 재검증 시간 (초)
export const dynamicParams = false;     // 동적 파라미터 허용 여부
export const fetchCache = 'auto';       // fetch 캐시 전략
export const preferredRegion = 'auto';  // 배포 리전

5. Client-side Router Cache (클라이언트 라우터 캐시)

개념

  • 브라우저에 저장되는 캐시
  • 페이지 간 이동을 효율적으로 처리하기 위해 RSC Payload 데이터를 보관
  • Next.js에서 자동으로 활성화됨

동작 원리

사용자 페이지 이동: / → /search → /book/1

1. 첫 방문시: 서버에서 전체 데이터 받음
2. 이후 방문시:
   - 공통 레이아웃은 캐시에서 재사용
   - 변경된 부분만 서버에서 받음

캐시되는 데이터

  • Layout Components: layout.tsx 파일들
  • Loading UI: loading.tsx 파일들
  • RSC Payload: 서버 컴포넌트 직렬화된 데이터

캐시 지속 시간

  • Static Routes: 5분
  • Dynamic Routes: 30초
  • 새로고침 시: 모든 캐시 삭제

수동 캐시 제어

import { useRouter } from 'next/navigation';

function MyComponent() {
  const router = useRouter();

  // 특정 경로 캐시 무효화
  router.refresh();

  // 프리페치 (미리 캐시에 저장)
  router.prefetch('/some-route');
}

6. 캐싱 전략 권장사항

Static Page 활용

  • 블로그 포스트, 상품 상세페이지 등 자주 변경되지 않는 콘텐츠
  • generateStaticParams로 주요 페이지 미리 생성
  • revalidate로 적절한 업데이트 주기 설정

Dynamic Page 사용 시기

  • 검색 결과, 사용자 대시보드, 실시간 데이터
  • useSearchParams 사용 시 반드시 Suspense로 감싸기
  • 불필요한 force-dynamic 사용 지양

성능 최적화 팁

  1. 공통 레이아웃 최대한 활용: 클라이언트 라우터 캐시 효과 극대화
  2. 적절한 Suspense 경계 설정: 필요한 부분만 동적으로 처리
  3. fetch 캐싱 전략: revalidate, no-store 옵션 적절히 활용
  4. 프리페치 활용: 사용자가 방문할 가능성이 높은 페이지 미리 로드

이 링크를 통해 구매하시면 제가 수익을 받을 수 있어요. 🤗

https://inf.run/4oB9v

반응형

'기술, 개발 > nextjs' 카테고리의 다른 글

9차 강의 노트 (서버 액션)  (0) 2025.08.28
8차 강의 노트 (스트리밍)  (3) 2025.08.28
6차 강의 노트 (데이터 페칭)  (0) 2025.08.28
5차 강의 노트 (앱라우터)  (0) 2025.08.28
4차 강의 노트 (앱라우터)  (1) 2025.08.28