Cloud CDN은 App Hosting에서 웹 앱을 지원하는 데 중요한 부분입니다. 백엔드에 대한 모든 요청은 먼저 Cloud CDN을 거칩니다. CDN에 이미 캐시된 콘텐츠는 웹 앱의 서버 코드를 실행하는 Cloud Run 서비스로 이동하지 않고 사용자에게 즉시 다시 제공됩니다. web.dev에서 CDN의 일반적인 이점에 대해 자세히 알아볼 수 있습니다.
기본 Cloud CDN 구성은 App Hosting에 의해 설정되며 수정할 수 없지만, 페이지 로드 속도를 높이고, 청구되는 캐시되지 않은 콘텐츠를 줄이고, Cloud Run으로의 트래픽을 최소화하기 위해 캐싱을 최적화할 수 있는 방법이 여러 가지 있습니다.
캐시 가능한 콘텐츠
다음 조건이 모두 참인 경우 Cloud CDN은 캐시에 응답을 저장합니다.
- 요청이 GET입니다. 
- 대답의 상태 코드가 - 200,- 203,- 204,- 206,- 300,- 301,- 302,- 307,- 308,- 404,- 405,- 410,- 421,- 451또는- 501입니다.
- 응답에 - max-age또는- s-maxage지시문이 있는- Cache-Control헤더가 있거나 향후 타임스탬프가 있는- Expires헤더가 있습니다.
- 응답에 - Age헤더 또는 명시적- public지시문이 있는- Cache-Control헤더가 있습니다.
- 응답 크기가 10MiB 이하입니다. 
다음 중 어느 것도 참이 아닙니다.
- 응답에 - Set-Cookie헤더가 있음
- 대답에 - Accept,- Accept-Encoding,- Access-Control-Request-Headers,- Access-Control-Request-Method,- Origin,- Sec-Fetch-Dest,- Sec-Fetch-Mode,- Sec-Fetch-Site,- X-Goog-Allowed-Resources,- X-Origin,- RSC,- Next-Router-State-Tree,- Next-Router-Prefetch,- Next-Router-Segment-Prefetch이외의 값이 있는- Vary헤더가 있습니다.
- 응답에 - no-store또는- private지시문이 있는- Cache-Control헤더가 있습니다.
- 요청에 - no-store지시문이 있는- Cache-Control헤더가 있습니다.
- 응답에 명시적 캐시 관리 지시문이 없는 한 요청에 - Authorization헤더가 있습니다.
캐시 제어 지시어로 동작 맞춤설정
Next.js
Next.js는 여러 요인에 따라 캐시 제어 지시어를 암시적으로 설정합니다. 하지만 next.config.js 파일에서 헤더를 수동으로 설정하여 이를 재정의할 수 있습니다. 예를 들어 페이지가 Cloud CDN에 캐시되지 않도록 하려면 다음을 실행합니다.
  /** @type {import('next').NextConfig} */
  const nextConfig = {
      headers: async () => [{
          source: "/YOUR_PRIVATE_PAGE",
          headers: [{
              key: "Cache-Control",
              value: "private"
          }],
      }],
  };
Angular
Angular SSR은 기본적으로 명시적 cache-control 지시어를 설정하지 않습니다. 서버 경로에서 cache-control 헤더를 지정하여 직접 추가할 수 있습니다. 예를 들어 Cloud CDN이 모든 페이지를 1시간 동안 캐시하도록 허용하려면 다음을 실행합니다.
import { RenderMode, ServerRoute } from '@angular/ssr';
export const serverRoutes: ServerRoute[] = [
  {
    path: '**',
    renderMode: RenderMode.Prerender,
    headers: {
      'Cache-Control': 'public, max-age=3600',
    }
  }
];
또는 특정 페이지가 캐시되지 않도록 하려면 다음 단계를 따르세요.
import { RenderMode, ServerRoute } from '@angular/ssr';
export const serverRoutes: ServerRoute[] = [
  // ... other routes
  {
    path: 'YOUR_PRIVATE_PAGE',
    renderMode: RenderMode.Server,
    headers: {
      'Cache-Control': 'private',
    }
  }
];
준수되는 지시어
Firebase App Hosting의 Cloud CDN 인스턴스는 다음 캐시 제어 지시문을 따릅니다.
| 지시문 | 요청 | 응답 | 
|---|---|---|
| no-store | 요청에 있는 경우 응답이 캐시되지 않습니다. | no-store가 포함된 응답은 캐시되지 않습니다. | 
| no-cache | 클라이언트가 원본에 재검증을 잠재적으로 시작하거나 강제하지 못하게 하기 위해 no-cache요청 지시문은 무시됩니다. | no-cache가 포함된 응답은 캐시되지만 제공하기 전에 원본으로 재검증해야 합니다. | 
| public | 해당 사항 없음 | 캐시 가능성에는 이 지시문이 필요하지 않지만 프록시에서 캐시해야 하는 콘텐츠에 포함하는 것이 좋습니다. | 
| private | 해당 사항 없음 | private지시문이 있는 응답은 응답이 캐시 가능한 것으로 간주되는 경우에도 Cloud CDN에 의해 캐시되지 않습니다. 클라이언트(예: 브라우저)는 여전히 결과를 캐시할 수 있습니다. 모든 응답 캐싱을 방지하려면no-store를 사용합니다. | 
| max-age=SECONDS | max-age요청 지시문은 무시됩니다. 이 헤더가 요청에 포함되지 않은 것처럼 캐시된 응답이 반환됩니다. | max-age지시문이 있는 응답은 정의된 초까지 캐시됩니다. | 
| s-maxage=SECONDS | 해당 사항 없음 | s-maxage지시문이 있는 응답은 정의된 초까지 캐시됩니다.max-age과s-maxage이 모두 존재하는 경우s‑maxage는 Cloud CDN에서 사용됩니다. 이 지시문이 있는 응답은 비활성 상태가 아닙니다.s-max-age(하이픈 2개)은 캐싱 목적에 유효하지 않습니다. | 
| max-stale=SECONDS | max-stale요청 지시문은 클라이언트가 허용할 최대 비활성 상태를 초 단위로 나타냅니다. Cloud CDN은 이를 받아들여 응답의 비활성 상태가max-stale지시문보다 짧은 경우에만 오래된 캐시된 응답을 반환합니다. 그렇지 않으면 요청을 처리하기 전에 재검증합니다. | 해당 사항 없음 | 
| stale-while-revalidate=SECONDS | 해당 사항 없음 | stale-while-revalidate가 있는 응답은 클라이언트에 최대 SECONDS까지 제공되고 재검증이 비동기식으로 발생합니다. | 
| must-revalidate | 해당 사항 없음 | must-revalidate가 포함된 응답은 만료된 후 원본 서버에서 재검증합니다. 이 지시문이 있는 응답은 비활성 상태가 아닙니다. | 
| proxy-revalidate | proxy-revalidate가 포함된 응답은 만료된 후 원본 서버에서 재검증합니다. 이 지시문이 있는 응답은 비활성 상태가 아닙니다. | |
| no-transform | 해당 사항 없음 | Cloud CDN에는 변환이 적용되지 않습니다. | 
캐시된 트래픽과 캐시되지 않은 트래픽 측정
App Hosting 콘솔의 사용량 탭에 있는 'Cloud CDN - 아웃바운드 대역폭' 그래프에는 캐시된 바이트와 캐시되지 않은 바이트가 표시되며 각 출시마다 표시가 있습니다. 이 그래프를 사용하여 캐시 최적화 노력의 효과를 측정할 수 있습니다.
경로 기반 모니터링을 사용하여 웹 앱의 특정 경로에 대한 캐시 적중률을 확인할 수도 있습니다.