문제와 원인
공개 응답 캐시는 caches.default만 선택해 open() 전용 저장소에서 저장·조회를 건너뛰었다. 저장소가 연결된 경우에도 고정 출처 CACHE_ORIGIN으로 키를 만들어, namespace·콘텐츠 키·빌드가 같은 A·B 출처의 요청이 충돌했다. A 응답을 저장하면 B 요청에도 A 본문이 반환됐다.
수정 전 코드
sharedCache / cacheRequest
좌우로 이동해 전체 내용을 확인하세요. 키보드: ←·→, Home·End
function sharedCache() {
const storage = globalThis.caches;
return storage?.default ?? null;
}
function cacheRequest(namespace: string, key: string) {
const url = new URL(`/api/${namespace}`, CACHE_ORIGIN);
url.searchParams.set("build", __BAEUMZIP_BUILD_SHA__.slice(0, 12));
url.searchParams.set("key", key);
return new Request(url, { method: "GET" });
}
수정 후 코드
sharedCache
default가 있으면 사용하고, 없으면 이름 있는 캐시를 open()으로 연다.
좌우로 이동해 전체 내용을 확인하세요. 키보드: ←·→, Home·End
async function sharedCache() {
const storage = globalThis.caches;
if (storage?.default) return storage.default;
if (!storage?.open) return null;
return storage.open("baeumzip-public-responses").catch(() => null);
}
cacheRequest
키는 요청 URL의 origin을 유지하고 pathname을 캐시 전용 경로로 바꾼다. 기존 쿼리를 지운 뒤 빌드·콘텐츠 키를 넣으며, 조회·저장 양쪽에 요청 객체를 전달해 같은 생성 함수를 사용한다.
좌우로 이동해 전체 내용을 확인하세요. 키보드: ←·→, Home·End
function cacheRequest(request: Request, namespace: string, key: string) {
const url = new URL(request.url);
url.pathname = `/__baeumzip-cache/${namespace}`;
url.search = "";
url.searchParams.set("build", __BAEUMZIP_BUILD_SHA__.slice(0, 12));
url.searchParams.set("key", key);
return new Request(url, { method: "GET" });
}
저장에는 Response.clone()을 사용해 호출자가 읽을 본문을 보존한다.
검증 결과
Node.js에서 수정 전후 원본 캐시 모듈을 Cache Storage 대역의 같은 공개 JSON 응답으로 실행하고, 저장소 2종·합성 출처 2개를 비교했다. Wrangler의 로컬 Cache API에서도 같은 모듈로 A 응답을 저장한 뒤 B 출처에서 조회했다.
좌우로 이동해 전체 내용을 확인하세요. 키보드: ←·→, Home·End
| 입력 조건 | 수정 전 | 수정 후 |
|---|---|---|
default에 A 응답 저장·조회 | 저장 1개, 적중 | 저장 1개, 적중 |
open() 전용 저장소에 응답 저장·조회 | 저장 0개, 미적중 | 저장 1개, 적중 |
| 정상 저장·조회한 저장소 형태 | 1/2종 | 2/2종 |
| A만 저장하고 B에서 같은 콘텐츠 키 조회 | A 본문 반환 | 미적중 |
| 이어서 B 응답 저장 | 기존 키 덮어쓰기, 키 1개 | A·B 각각 저장, 키 2개 |
| B 저장 후 B에서 다시 조회 | B 본문 반환 | B 본문 반환 |