Skip to content
iik89
Go back

마이크로 캐싱과 컴포넌트 단위 핀셋 통제: 하이브리드 렌더링 아키텍처

1. 매크로 캐싱(Macro Caching)의 한계

Next.js 14 이전 시대를 지배했던 캐싱 방식은 페이지(Route) 단위의 일괄 캐싱, 즉 매크로 캐싱(Macro Caching)이었다. 이 방식은 하나의 화면 안에 서로 다른 갱신 주기를 가진 영역이 공존하는 순간 치명적인 구조적 모순을 드러낸다.

실무 사례: 의료 예약 서비스 상세 페이지

병원 예약 서비스의 진료과 상세 페이지를 예시로 살펴본다.

영역비율특성
의료진 소개, 진료 안내, 병원 위치 정보90%수개월 단위로 거의 변경되지 않는 정적 콘텐츠
오늘의 잔여 예약 슬롯, 로그인한 사용자의 예약 현황10%분 단위로 변동되는 실시간 데이터

All or Nothing: 강요된 이분법

매크로 캐싱 환경에서 아키텍트는 두 가지 극단 중 하나를 선택해야 했다.

선택지 1 — 전체 캐싱 (성능 우선)

페이지 전체를 결빙하면 정적 콘텐츠는 0.001초 만에 반환된다. 그러나 실시간 예약 슬롯과 사용자 예약 현황까지 함께 얼어버린다. 이미 마감된 시간대가 ‘예약 가능’으로 노출되는 데이터 부패가 발생한다.

선택지 2 — 전체 동적 렌더링 (신선도 우선)

실시간성을 확보하기 위해 페이지 전체를 동적으로 처리한다. 사용자 로그인 상태 확인을 위해 cookies() 함수를 단 한 줄 작성하는 순간, 프레임워크는 페이지 전체의 캐시를 파기한다. 변경 빈도가 극히 낮은 90%의 정적 콘텐츠까지 매 요청마다 DB를 조회하여 새롭게 그려내야 한다.

결론적으로 1초마다 변하는 단 10%의 데이터 때문에, 1년 내내 동일한 90%의 콘텐츠까지 매 요청마다 서버 연산을 소모하는 극심한 비효율이 발생한다.


2. 마이크로 캐싱(Micro Caching): 캐싱 단위의 혁명

이 구조적 모순을 해결하기 위해 Next.js 15는 캐싱의 단위를 페이지(Route) 에서 컴포넌트(Component)함수(Function) 레벨로 극단적으로 세분화했다. 이것이 마이크로 캐싱(Micro Caching) 이다.

구현 코드

// Next.js 15 마이크로 캐싱 아키텍처 실무 예시

export default function MedicalDetailPage() {
  return (
    <div className="layout">
      {/* 10% 동적 영역: 요청마다 새롭게 렌더링 */}
      <LiveReservationSlots />
      <UserReservationStatus />

      {/* 90% 정적 영역: 이 컴포넌트만 독립적으로 결빙 */}
      <HeavyDoctorProfileSection />
    </div>
  );
}

// 아키텍트의 핀셋 통제: 무거운 DB 조회를 수행하는 컴포넌트만 단독 캐싱
async function HeavyDoctorProfileSection() {
  'use cache'; // 이 컴포넌트의 렌더링 결과물만 영구적으로 결빙한다.

  // 이 쿼리는 최초 1회만 실행되고, 이후 요청에서는 연산이 완전히 생략된다.
  const profile = await db.doctor.getFullProfile();

  return <article>{profile.description}</article>;
}

'use cache' 지시어란?

'use cache'는 리액트 서버 컴포넌트 또는 서버 함수의 최상단에 선언하는 캐싱 지시어다. 이 선언이 존재하면 프레임워크는 해당 컴포넌트나 함수의 실행 결과물을 캐시에 저장한다. 이후 동일한 요청이 발생할 경우 내부 연산 전체를 생략(Bypass)하고 저장된 결과물을 즉시 반환한다.

fetch 옵션 기반의 데이터 캐싱과 달리, 어떤 리액트 컴포넌트든 일반 함수든 선언 하나만으로 독립적으로 캐싱 대상을 지정할 수 있다.


3. 컴포넌트 트리 실행 흐름

위 코드가 서버에서 처리되는 순서를 시간선(Timeline) 기준으로 분석한다.

1) 부모 컴포넌트 실행

MedicalDetailPage가 실행되어 전체 화면의 레이아웃 구조를 구성한다.

2) 동적 컴포넌트 렌더링

LiveReservationSlotsUserReservationStatus는 사용자 쿠키를 읽고 DB와 실시간으로 통신한다. 매 요청마다 서버 연산이 발생한다.

3) 'use cache' 지시어 감지

HeavyDoctorProfileSection 내부에서 'use cache' 지시어를 발견하는 순간, 프레임워크는 내부의 DB 쿼리 실행을 완전히 생략한다.

4) 캐시 반환

캐시에 저장된 HTML 조각을 0.001초 만에 꺼내어 부모 컴포넌트에 전달한다. 무거운 연산 비용이 발생하지 않는다.


4. 스위트스팟(Sweet Spot): 하이브리드 렌더링의 완성

마이크로 캐싱이 달성하는 상태를 시스템 공학 관점에서 스위트스팟(Sweet Spot) 이라 정의한다.

스위트스팟은 스포츠 용어에서 유래했다. 테니스 라켓이나 골프 클럽에서 타격 에너지가 가장 효율적으로 전달되는 최적의 지점을 뜻하며, 시스템 공학에서는 상충하는 복수의 제약 조건 속에서 양쪽의 이점을 동시에 극대화하는 최적의 균형점을 의미한다.

웹 아키텍처에서 스위트스팟은 다음 두 목표가 모순 없이 교차하는 지점이다.

목표달성 방법결과
서버 성능 극대화90% 정적 영역을 캐시에서 즉시 반환연산 비용 극소화
데이터 100% 신선도10% 동적 영역을 매 요청마다 DB 직접 조회실시간 정확성 보장

5. 매크로 캐싱 vs 마이크로 캐싱 비교

구분매크로 캐싱 (Next.js 14 이하)마이크로 캐싱 (Next.js 15)
캐싱 단위페이지(Route) 전체컴포넌트 / 함수 단위
제어 방식All or Nothing핀셋 선택적 적용
정적 영역 처리동적 영역과 함께 일괄 처리독립적으로 결빙 가능
동적 영역 처리페이지 전체가 동적으로 전환해당 컴포넌트만 실시간 처리
비효율10% 때문에 90%를 매번 재연산각 영역의 특성에 맞게 독립 처리
선언 방법fetch 옵션으로 제한'use cache' 지시어로 어디서든 적용 가능

마이크로 캐싱은 “페이지 전체를 어떻게 처리할 것인가”라는 질문을 “각 컴포넌트를 어떻게 처리할 것인가”라는 질문으로 전환한다. 이 패러다임 전환이 매크로 캐싱이 강요했던 All or Nothing의 이분법을 완전히 해소한다.


Share this post on:

Previous Post
PPR과 마이크로 캐싱: cacheComponents와 Suspense 기반 하이브리드 렌더링
Next Post
ISR과 SWR 패턴: 시간 기반 캐시 재검증 아키텍처