RSC
cacheSignal은 현재 React Server Components에서만 사용돼요.
cacheSignal을 사용하면 cache()의 수명이 끝났는지 알 수 있어요.
const signal = cacheSignal();
쉽게 말해서, cache()로 캐싱된 작업이 더 이상 필요 없을 때를 감지할 수 있게 해주는 거예요. 이걸 통해 불필요한 작업을 취소할 수 있죠.
cacheSignalcacheSignal을 호출하면 AbortSignal을 얻을 수 있어요.
// 예시
import {cacheSignal} from 'react';
async function Component() {
await fetch(url, { signal: cacheSignal() });
}
React가 렌더링을 마치면, AbortSignal이 중단(abort)돼요. 이를 통해 더 이상 필요 없는 진행 중인 작업을 취소할 수 있어요.
렌더링이 완료된 것으로 간주되는 경우는 다음과 같아요:
이 함수는 어떤 매개변수도 받지 않아요.
cacheSignal은 렌더링 중에 호출되면 AbortSignal을 반환해요. 그렇지 않으면 cacheSignal()은 null을 반환해요.
cacheSignal은 현재 React Server Components에서만 사용할 수 있어요. Client Components에서는 항상 null을 반환해요. 앞으로는 클라이언트 캐시가 새로고침되거나 무효화될 때 Client Component에서도 사용될 예정이에요. 그러니까 클라이언트에서 항상 null이 될 거라고 가정하면 안 돼요.cacheSignal은 null을 반환해요. 이건 현재 스코프가 영원히 캐시되지 않는다는 걸 명확히 하기 위해서예요.진행 중인 요청을 중단하려면 cacheSignal을 호출하세요.
// 예시
import {cache, cacheSignal} from 'react';
const dedupedFetch = cache(fetch);
async function Component() {
await dedupedFetch(url, { signal: cacheSignal() });
}
⚠️ 주의
렌더링 바깥에서 시작된 비동기 작업을 중단하는 데는
cacheSignal을 사용할 수 없어요. 예를 들어:// 예시 import {cacheSignal} from 'react'; // 🚩 주의: `Component`의 렌더링이 끝나도 요청이 실제로 중단되지 않아요. const response = fetch(url, { signal: cacheSignal() }); async function Component() { await response; }위 코드에서
fetch가 컴포넌트 바깥에서 호출되기 때문에,cacheSignal이 해당 요청을 제대로 취소할 수 없어요.cacheSignal은 렌더링 컨텍스트 안에서 시작된 작업에만 적용되거든요.
함수가 에러를 던지면, 그건 취소 때문일 수도 있어요 (예: 데이터베이스 연결이 닫혔을 때). aborted 속성을 사용해서 에러가 취소 때문인지 아니면 실제 에러인지 확인할 수 있어요. 취소로 인한 에러는 무시하고 싶을 수 있죠.
// 예시
import {cacheSignal} from "react";
import {queryDatabase, logError} from "./database";
async function getData(id) {
try {
return await queryDatabase(id);
} catch (x) {
if (!cacheSignal()?.aborted) {
// 취소로 인한 에러가 아니라 실제 에러일 때만 로그를 남겨요
logError(x);
}
return null;
}
}
async function Component({id}) {
const data = await getData(id);
if (data === null) {
return <div>No data available</div>;
}
return <div>{data.name}</div>;
}
위 코드를 좀 더 설명하자면:
queryDatabase(id)가 에러를 던지면 catch 블록으로 들어가요.cacheSignal()?.aborted를 확인해서, 만약 aborted가 true가 아니라면 (즉, 취소 때문이 아니라면) 실제 에러이므로 logError(x)로 에러를 기록해요.null을 반환해요.