React ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ

cacheSignal์€ ํ˜„์žฌ React ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ์—์„œ๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

cacheSignal์„ ์‚ฌ์šฉํ•˜๋ฉด cache() ์ˆ˜๋ช…์ด ์–ธ์ œ ๋๋‚˜๋Š”์ง€ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

const signal = cacheSignal();

๋ ˆํผ๋Ÿฐ์Šค

cacheSignal

cacheSignal์„ ํ˜ธ์ถœํ•˜๋ฉด AbortSignal์„ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

import {cacheSignal} from 'react';
async function Component() {
await fetch(url, { signal: cacheSignal() });
}

React๊ฐ€ ๋ Œ๋”๋ง์„ ์™„๋ฃŒํ•˜๋ฉด AbortSignal์ด ์ค‘๋‹จ๋ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ๋” ์ด์ƒ ํ•„์š”ํ•˜์ง€ ์•Š์€ ์ง„ํ–‰ ์ค‘์ธ ์ž‘์—…์„ ์ทจ์†Œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ Œ๋”๋ง์ด ์™„๋ฃŒ๋œ ๊ฒƒ์œผ๋กœ ๊ฐ„์ฃผํ•˜๋Š” ๊ฒฝ์šฐ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • React๊ฐ€ ์„ฑ๊ณต์ ์œผ๋กœ ๋ Œ๋”๋ง์„ ์™„๋ฃŒํ•œ ๊ฒฝ์šฐ
  • ๋ Œ๋”๋ง์ด ์ค‘๋‹จ๋œ ๊ฒฝ์šฐ
  • ๋ Œ๋”๋ง์ด ์‹คํŒจํ•œ ๊ฒฝ์šฐ

๋งค๊ฐœ๋ณ€์ˆ˜

์ด ํ•จ์ˆ˜๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๋ฐ›์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๋ฐ˜ํ™˜๊ฐ’

cacheSignal์€ ๋ Œ๋”๋ง ์ค‘์— ํ˜ธ์ถœ๋˜๋ฉด AbortSignal์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ ์™ธ์˜ ๊ฒฝ์šฐ์— cacheSignal()์€ null์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

์ฃผ์˜ ์‚ฌํ•ญ

  • cacheSignal์€ ํ˜„์žฌ React ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ์—์„œ๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ์—์„œ๋Š” ํ•ญ์ƒ null์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ํ–ฅํ›„ ํด๋ผ์ด์–ธํŠธ ์บ์‹œ๊ฐ€ ๊ฐฑ์‹ ๋˜๊ฑฐ๋‚˜ ๋ฌดํšจํ™”๋  ๋•Œ ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ์—์„œ๋„ ์‚ฌ์šฉ๋  ์˜ˆ์ •์ž…๋‹ˆ๋‹ค. ํด๋ผ์ด์–ธํŠธ์—์„œ ํ•ญ์ƒ 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';
// ๐Ÿšฉ Pitfall: The request will not actually be aborted if the rendering of `Component` is finished.
const response = fetch(url, { signal: cacheSignal() });
async function Component() {
await response;
}

React๊ฐ€ ๋ Œ๋”๋ง์„ ์™„๋ฃŒํ•œ ํ›„ ์˜ค๋ฅ˜ ๋ฌด์‹œํ•˜๊ธฐ

ํ•จ์ˆ˜๊ฐ€ ์˜ค๋ฅ˜๋ฅผ ๋˜์ง€๋Š” ๊ฒฝ์šฐ ์ทจ์†Œ๋กœ ์ธํ•œ ๊ฒƒ์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. (์˜ˆ๋ฅผ ๋“ค์–ด, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ์ด ๋‹ซํžŒ ๊ฒฝ์šฐ) aborted ์†์„ฑ์„ ์‚ฌ์šฉํ•˜์—ฌ ์˜ค๋ฅ˜๊ฐ€ ์ทจ์†Œ๋กœ ์ธํ•œ ๊ฒƒ์ธ์ง€ ์‹ค์ œ ์˜ค๋ฅ˜์ธ์ง€ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ทจ์†Œ๋กœ ์ธํ•œ ์˜ค๋ฅ˜๋Š” ๋ฌด์‹œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

import {cacheSignal} from "react";
import {queryDatabase, logError} from "./database";

async function getData(id) {
try {
return await queryDatabase(id);
} catch (x) {
if (!cacheSignal()?.aborted) {
// only log if it's a real error and not due to cancellation
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>;
}