GraphQL SWR Caching (NestJS, 코드 우선)
개요
의도에 의한 캐싱, 메커니즘이 아닙니다. 하나의 정책 형태, 하나의 관찰 가능한 이벤트 스트림, 하나의 요청별 추적. 기본적으로 서비스 수준에서 마운트하고, 측정 결과에 따라 필드/연산/전송 수준으로 확장합니다.
모든 결정을 형성하는 세 가지 엄격한 진실:
- Apollo Server에는 내장된 stale-while-revalidate가 없습니다.
responseCachePlugin은 TTL 전용이며 연산 수준입니다. 실제 SWR은 자체 레이어(async-cache-dedupe, 또는 Mercurius 드라이버의mercurius-cache) 또는 CDN에서 제공됩니다. - 범위 기본값은
public입니다. 공개 항목은 모든 호출자가 그대로 공유하므로, 결과가 모든 호출자에 대해 바이트 단위로 동일한 경우에만 올바릅니다. 값이 호출자에 따라 달라지는 순간 반드시perUser로 표시해야 합니다. 그렇지 않으면 데이터가 누출됩니다. - Nest 인터셉터는 서비스 메서드를 래핑하지 않으며,
@nestjs/cache-manager의CacheInterceptor는 GraphQL에서 작동하지 않습니다. 따라서 필요한 서비스 수준 데코레이터는 프레임워크 인터셉터가 아니라 중복 제거 엔진을 래핑하는 메서드 래퍼입니다.
사용 시기
- NestJS GraphQL(코드 우선)에서 리졸버/서비스가 반복적으로 DB 또는 업스트림 API에 접근하는 경우.
- TTL 만료 시 지연 시간 급증 및 스탬피드(진정한 SWR)를 제거해야 하는 경우.
- 다중 사용자 캐시 안전성/누출에 대해 추론해야 하는 경우.
- 적중/오래된 데이터/미스 결정에 대한 가시성이 필요한 경우.
- 개발, CI 또는 인시던트 중 하나의 플래그로 캐싱을 완전히 끄고 싶은 경우(섹션 1,
setup-disable-switch참조). - 처음으로 앱에 캐싱 기능을 연결하는 경우(섹션 1 참조).
사용하지 말아야 할 때:
- 이미 공용 GET/APQ 트래픽에 대해 응답 캐싱을 수행하는 CDN 뒤에 있는 경우 - 거기서 시작하세요.
- 쓰기/변경 경로이거나, 재사용성이 낮고 읽기 증폭이 적은 사용자별 데이터인 경우(캐싱은 이득에 비해 위험만 추가합니다).
콜백 계약
key, @CacheTag, @InvalidateTags는 함수를 사용합니다. 인수를 올바르게 설정하지 않으면 캐시는 조용히 미스되고 태그는 조용히 제거되지 않습니다.
| 콜백 | 시그니처 | args의 의미 |
|---|---|---|
key | (args, ctx) => unknown[] | Promise<unknown[]> | 메서드의 인수 목록, 호출 순서대로 — args[0], args.id가 아님 |
@CacheTag | (result, args) => string[] | null | 동일한 목록; result는 메서드의 반환 값 |
@InvalidateTags | (result, args) => string[] | 동일한 목록; result는 쓰기의 반환 값 |
- 위치 기반, 명명되지 않음.
getTitle(id: string)의 경우 id는args[0]입니다. - 두 태그 콜백 모두에서 결과가 먼저 옵니다. 원시 엔진 자체의
references는(args, key, result)— 순서가 다르고 첫 번째 인수가 다릅니다(driver-async-cache-dedupe참조). ctx(userId,tenantId,locale,gen포함)는 요청에서 파생되며buildCacheContext에 의해 조합됩니다. 요청 외부에서는 비어 있으므로, 작업은 필요한 것을 인수로 전달합니다.- 타이핑: 기본값은
unknown[]/unknown입니다. 튜플(@Cacheable<[string]>,@CacheTag<[string]>)에 주석을 추가하지 않으면 콜백 본문이 컴파일되지 않습니다. - 필드 수준은 다릅니다: 여기서
args는 리졸버의 명명된 인수 객체이고ctx는 GraphQL 컨텍스트입니다(driver-mercurius-cache).
전체 계약, 키 번들 { a, k, u } 및 직렬화 에지 케이스: policy-key-derivation. 런타임 구현: setup-decorator-runtime.
우선순위별 규칙 카테고리
| 우선순위 | 카테고리 | 영향 | 접두어 |
|---|---|---|---|
| 1 | 일회성 설정 | 치명적 | setup- |
| 2 | 캐시 정책 | 치명적 | policy- |
| 3 | 누수 안전성 | 치명적 | safety- |
| 4 | 무효화 | 높음 | invalidation- |
| 5 | 관찰 가능성 | 중간 | observability- |
| 6 | 드라이버 | 중간 | driver- |
빠른 참조
1. 일회성 설정 (치명적)
setup-decorator-runtime- 안정적인 이름으로 메서드 래퍼인 데코레이터 구현setup-disable-switch- 서비스 수준 캐시를 우회하는 하나의 설정 스위치 제공setup-engine-choice- 중복 제거 엔진 사용, TTL은 초 단위로 계산setup-fail-open- 장애 허용, 오류는 절대 캐시하지 않음setup-file-placement- 가져오는 주체에 따라 기능 배치setup-identity-context- Scope.REQUEST가 아닌 AsyncLocalStorage에서 호출자 읽기setup-module-wiring- forRootAsync로 캐시 모듈을 한 번만 연결setup-storage-and-invalidation- 무효화 활성화, referencesTTL 및 GC 설정
2. 캐시 정책 (치명적)
policy-five-knobs- 다섯 가지 노브 이해policy-key-derivation- 키를 자동으로 파생, JSON.stringify 사용 금지policy-mount-at-service- 기본적으로 서비스 수준에서 마운트policy-one-writing-pattern- 데코레이터가 유일한 작성 패턴policy-service-escape-hatch- 서비스 API는 두 번째 패턴이 아닌 이스케이프 해치
3. 누수 안전성 (치명적)
safety-default-public- 범위 기본값은 public — 호출자에 따라 달라지는 읽기는 perUser로 표시safety-key-dimensions- 범위는 사용자만 다룸 — 다른 모든 차원은 키에 포함safety-no-leak-checklist- 모든 캐시된 읽기에 대해 누수 방지 체크리스트 실행
4. 무효화 (높음)
invalidation-after-success- 성공적인 쓰기 후에만 무효화invalidation-atomic-purge- 원자적으로 제거하고 태그 카디널리티 제한invalidation-generation-prefix- 대규모 또는 광범위한 도메인에 세대 접두어 사용invalidation-tags-purge-only- 태그는 제거 전용, 조회용 아님
5. 관찰 가능성 (중간)
observability-limits-of-events- 엔진이 보고할 수 없는 것 이해observability-metrics-and-tests- 수정 사항을 증명하는 메트릭 추적, 결과 기반 테스트observability-per-request-trace- 요청별 추적 제공, GraphQL에서는 개발 전용observability-structured-events- 로그 문자열이 아닌 구조화된 캐시 이벤트 내보내기
6. 드라이버 (중간)
driver-apollo-response-cache- 옵션 C — Apollo responseCachePlugin (연산 수준, TTL 전용)driver-apollo-vs-mercurius- 드라이버에 따라 필드 수준 옵션 선택driver-async-cache-dedupe- 옵션 A — async-cache-dedupe (서비스 수준, 전송 독립적)driver-cdn-transport- 옵션 E — 전송 / CDN SWR (공용 읽기 전용)driver-envelop-response-cache- 옵션 D — Envelop useResponseCache (NestJS에 기본 제공되지 않음)driver-federation-router- 페더레이션 전용 — Apollo Router 응답 캐싱driver-mercurius-cache- 옵션 B — mercurius-cache (필드 수준, 실제 SWR)driver-version-pinning- 버전 고정 — 이 영역은 자주 변경됨
사용 방법
일회성 설정 섹션부터 시작한 다음, 현재 직면한 결정에 대해 정책, 안전성 및 무효화 규칙을 읽으십시오. 규칙 파일은 rules/ 아래에 있습니다:
રules/setup-module-wiring.md
rules/_sections.md
각 규칙 파일에는 다음이 포함됩니다:
- 규칙의 내용과 방지하는 실패
- 설명이 포함된 잘못된 예제
- 설명이 포함된 올바른 예제
- 참조
전체 컴파일된 문서
모든 규칙이 하나의 문서에 확장된 전체 가이드는 AGENTS.md를 참조하십시오.