Reuse Cached Data For Rendering

Reusing Cached Data

Relay๋Š” app์ด ์‚ฌ์šฉ๋˜๋Š” ๋™์•ˆ ๋ฐœ์ƒํ•œ ์—ฌ๋Ÿฌ๋ฒˆ์˜ ์ฟผ๋ฆฌ์— ์˜ํ•ด ๋ฐ›์•„์™€์ง„ ๋ฐ์ดํ„ฐ๋“ค์„ ์ถ•์ ์‹œํ‚ค๊ณ  ์บ์‹ฑํ•ด๋‘”๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ข…์ข… ์šฐ๋ฆฌ๋Š” ๋„คํŠธ์›Œํฌ๋ฅผ ํ†ตํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ์ƒˆ๋กœ ๋ฐ›์•„์˜ค์ง€ ์•Š๊ณ  ์ด๋ ‡๊ฒŒ ์บ์‹ฑ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๊ธธ ์›ํ•  ๋•Œ๊ฐ€ ์žˆ๋‹ค.

์•„๋ž˜ ์ƒํ™ฉ๋“ค์ด ์ด๋ ‡๊ฒŒ โ€˜์บ์‹ฑ๋œ ๋ฐ์ดํ„ฐโ€™๋ฅผ ์ด์šฉํ• ๋งŒํ•œ ์˜ˆ์‹œ์ด๋‹ค.

  • ์•ฑ ๋‚ด์˜ ํƒญ๋“ค ์‚ฌ์ด๋ฅผ ์ด๋™ํ•  ๋•Œ, ๊ทธ๋ฆฌ๊ณ  ๊ทธ ํƒญ๋“ค์„ ์ด๋™ํ•  ๋•Œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„์™€์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ์— ์ด๋ฏธ ํ•œ ๋ฒˆ ๋ฐฉ๋ฌธํ•œ ์ ์ด ์žˆ๋Š” ํƒญ์€ ์บ์‹ฑ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋‹ค์‹œ ๋„คํŠธ์›Œํฌ ์š”์ฒญ์ด ๋ฐœ์ƒํ•˜์ง€ ์•Š์Œ.

  • ํ•œ๋ฒˆ ํ”ผ๋“œ์— ๋ Œ๋”๋ง๋œ ์ ์ด ์žˆ๋Š” ํฌ์ŠคํŠธ์— ๋‹ค์‹œ ์ ‘๊ทผํ•˜๋ ค ํ•˜๋Š” ๊ฒฝ์šฐ, ํฌ์ŠคํŠธ์˜ permalink ํŽ˜์ด์ง€๋Š” ์บ์‹œ๋˜์–ด์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ฆ‰์‹œ ๋ Œ๋”๋ง ๋จ.

    • ๋งŒ์•ฝ ํฌ์ŠคํŠธ์˜ permalink ํŽ˜์ด์ง€์—์„œ ์ง€๊ธˆ local์—์„œ ๊ฐ–๊ณ ์žˆ๋Š” ๊ฒƒ๋ณด๋‹ค ๋” ๋งŽ์€ ๋ฐ์ดํ„ฐ๋ฅผ ํ•„์š”๋กœ ํ•˜๋”๋ผ๋„, ๋‹น์žฅ์€ ๊ฐ–๊ณ ์žˆ๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ๋ Œ๋”๋ง์„ block์‹œํ‚ค์ง€ ์•Š์Œ.

Fetch Policies

์บ์‹œ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ์žฌ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์€ loadQuery ํ•จ์ˆ˜ ๋‚ด๋ถ€์— fetchPolicy ์˜ต์…˜์„ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์ด๋‹ค. (์ด loadQuery ํ•จ์ˆ˜๋Š” useQueryLoader ํ›…์— ์˜ํ•ด ๋ฐ˜ํ™˜๋œ ํ•จ์ˆ˜๋ฅผ ์˜๋ฏธ)

const React = require('React');
const {graphql} = require('react-relay');

function AppTabs() {
  const [
    queryRef,
    loadQuery,
  ] = useQueryLoader<HomeTabQueryType>(HomeTabQuery);

  const onSelectHomeTab = () => {
    loadQuery({id: '4'}, {fetchPolicy: 'store-or-network'});
  }

  // ...
}
  • useQueryLoader ํ›…์— ์˜ํ•ด ๋ฐ˜ํ™˜๋œ loadQuery ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ ์˜ต์…˜์œผ๋กœ fetchPolicy ๋ฅผ ์ถ”๊ฐ€ํ–ˆ๋‹ค. store-or-network ์˜ต์…˜์„ ์คฌ๊ธฐ ๋•Œ๋ฌธ์— ๋จผ์ € ์บ์‹œ ๋ฐ์ดํ„ฐ๋ฅผ ํ™•์ธํ•˜๊ณ , ๋ฐ์ดํ„ฐ๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ์—๋งŒ ์ƒˆ๋กœ์šด ๋ฐ์ดํ„ฐ๋ฅผ fetchํ•˜๋„๋ก ํ•œ๋‹ค.

  • fetchPolicy ๋Š” ๋‹ค์Œ ๋‚ด์šฉ๋“ค์„ ๊ฒฐ์ •ํ•œ๋‹ค.

    • ๋กœ์ปฌ ์บ์‹œ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ• ์ง€

    • store(์บ์‹œ)์— ์žˆ๋Š” ๋ฐ์ดํ„ฐ์˜ ๊ฐ€์šฉ ์—ฌ๋ถ€์— ๋”ฐ๋ผ ์„œ๋ฒ„์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ fetchํ• ์ง€

๊ธฐ๋ณธ์ ์œผ๋กœ, Relay๋Š” ๋กœ์ปฌ ์บ์‹œ์— ์žˆ๋Š” ์ฟผ๋ฆฌ๋ฅผ ์ฝ์–ด ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋ ค ํ•œ๋‹ค. ํ•˜์ง€๋งŒ ๊ทธ ์ฟผ๋ฆฌ์— ๋Œ€ํ•œ ๋ฐ์ดํ„ฐ๊ฐ€ ์—†๊ฑฐ๋‚˜ ์—…๋ฐ์ดํŠธ๊ฐ€ ํ•„์š”ํ•  ๊ฒฝ์šฐ์—๋Š” ์ฟผ๋ฆฌ๋ฅผ ํ†ตํ•ด ๋„คํŠธ์›Œํฌ ์š”์ฒญ์„ ๋ณด๋‚ด ์ „์ฒด ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค์‹œ ๊ฐ€์ ธ์˜จ๋‹ค. ์œ„์— ์žˆ๋Š” store-or-network ์˜ต์…˜์€ ์‚ฌ์‹ค Relay์˜ ๊ธฐ๋ณธ ์˜ต์…˜์ด๋‹ค.

์•„๋ž˜์™€ ๊ฐ™์€ ๋‹ค๋ฅธ ์˜ต์…˜๋“ค๋„ ์žˆ๋‹ค.

  • store-and-network : ๋กœ์ปฌ ์บ์‹œ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ผ๋‹จ ์“ฐ์ง€๋งŒ, ํ•ญ์ƒ ๋„คํŠธ์›Œํฌ ์š”์ฒญ์„ ๋‹ค์‹œ ๋ณด๋ƒ„. ๋ฐ์ดํ„ฐ๊ฐ€ ์žˆ๋“  ์—†๋“ , ์ตœ์‹ ์˜ ๊ฒƒ์ด๋“  ์•„๋‹ˆ๋“  ์ƒ๊ด€ ์—†์Œ.

  • network-only : ๋กœ์ปฌ ์บ์‹œ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ํ•ญ์ƒ ๋„คํŠธ์›Œํฌ ์š”์ฒญ์„ ํ†ตํ•ด ์ƒˆ๋กœ ๋ฐ›์€ ๋ฐ์ดํ„ฐ๋ฅผ ์ด์šฉ.

  • store-only : ์˜ค์ง ๋กœ์ปฌ ์บ์‹œ์˜ ๋ฐ์ดํ„ฐ๋งŒ ์žฌ์‚ฌ์šฉํ•จ. ๋„คํŠธ์›Œํฌ ์š”์ฒญ์€ ๋ณด๋‚ด์ง€ ์•Š์Œ. ์ด ๋•Œ๋ฌธ์— ๋ฐ์ดํ„ฐ ์ผ๊ด€์„ฑ์— ๋Œ€ํ•œ ์ฑ…์ž„์€ ๊ฐœ๋ฐœ์ž์—๊ฒŒ ์žˆ์Œ.

Availability of Data

Relay๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ โ€˜๊ฐ€์šฉํ•œ์ง€โ€™์— ๋Œ€ํ•ด ๋‘๊ฐ€์ง€ ์ฒ™๋„๋ฅผ ํ†ตํ•ด ํŒ๋‹จํ•œ๋‹ค.

  1. Presence of Data

  2. Staleness of Data

Presence of Data

Relay store์— ์žˆ๋Š” ๋ฐ์ดํ„ฐ๋Š” ์ˆ˜๋ช…์ด ์žˆ๋Š”๋ฐ, ์ด ์ˆ˜๋ช…์€ ๋ฐ์ดํ„ฐ๊ฐ€ ๊ฐ€์šฉํ•œ์ง€๋ฅผ ํŒ๋‹จํ•  ์ˆ˜ ์žˆ๋Š” ์ค‘์š”ํ•œ ์ฒ™๋„์ด๋‹ค. ๋ณดํ†ต Relay store ์•ˆ์— ์žˆ๋Š” ๋ฐ์ดํ„ฐ๋Š” ์ฒซ fetch ์ดํ›„ ๊ณ„์† ์กด์žฌํ•œ๋‹ค. ๋งŒ์•ฝ ํ•œ๋ฒˆ๋„ fetchํ•œ ์ ์ด ์—†๋Š” ๋ฐ์ดํ„ฐ๋ผ๋ฉด store์—๋Š” ์กด์žฌํ•˜์ง€ ์•Š์„ ๊ฒƒ์ด๋‹ค.

๊ทธ์น˜๋งŒ ์ˆ˜๋งŽ์€ ์ฟผ๋ฆฌ๋“ค์„ ํ†ตํ•ด ๊ฐ€์ ธ์˜จ ๋ฐ์ดํ„ฐ๋“ค์„ ์ „๋ถ€ ๋ฉ”๋ชจ๋ฆฌ์— ์ €์žฅํ•ด๋‘˜ ์ˆ˜๋Š” ์—†๋‹ค. ์ „๋ถ€ ์ €์žฅํ•ด๋‘”๋‹ค๋ฉด ์šฐ๋ฆฌ๋Š” ๋ถˆํ•„์š”ํ•˜๊ฒŒ ๋ฐฉ๋Œ€ํ•˜๊ณ  ๋‚ก์€ ๋ฐ์ดํ„ฐ๋ฅผ ์œ„ํ•ด ๋งŽ์€ ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„์„ ๋‚ญ๋น„ํ•˜๊ฒŒ ๋  ๊ฒƒ์ด๋‹ค.

์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด Relay๋Š” Garbage Collector๋ผ๊ณ  ํ•˜๋Š” ํ”„๋กœ์„ธ์Šค๋ฅผ ๋Œ๋ฆฐ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ๋” ์ด์ƒ ์“ฐ์ง€ ์•Š๋Š” ๋ฐ์ดํ„ฐ๋“ค์„ ์‚ญ์ œํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค.

Garbage Collection in Relay

Relay๋Š” ํŠนํžˆ ๋กœ์ปฌ in-memory store์—์„œ Garbage Collection์„ ์ˆ˜ํ–‰ํ•œ๋‹ค. ์–ด๋–ค ์ปดํฌ๋„ŒํŠธ์—๊ฒŒ๋„ ์ฐธ์กฐ๋˜์ง€ ์•Š๋Š” ๋ฐ์ดํ„ฐ๋“ค์„ ์‚ญ์ œํ•œ๋‹ค.

๊ทธ์น˜๋งŒ ๋ฐ์ดํ„ฐ๋ฅผ ์žฌ์‚ฌ์šฉํ•  ๊ฐ€๋Šฅ์„ฑ๋„ ์—ผ๋‘์— ๋‘ฌ์•ผ ํ•œ๋‹ค. ๋งŒ์•ฝ ๋ฐ์ดํ„ฐ๊ฐ€ ๋„ˆ๋ฌด ๋นจ๋ฆฌ ์‚ญ์ œ๋ผ์„œ ์žฌ์‚ฌ์šฉํ•˜๋ ค๊ณ  ๋ณด๋‹ˆ ์—†๋Š” ๊ฒฝ์šฐ์—” ๋„คํŠธ์›Œํฌ๋กœ๋ถ€ํ„ฐ ๋‹ค์‹œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„์™€์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฐ”๋กœ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๊ฒŒ ๋œ๋‹ค. ๊ทธ๋ž˜์„œ ์žฌ์‚ฌ์šฉ์ด ์ผ์–ด๋‚  ๋ฐ์ดํ„ฐ๋“ค์€ ํ™•์‹คํ•˜๊ฒŒ โ€˜์žฌ์‚ฌ์šฉ ํ• ๊ฑฐ๋‹คโ€™๋ผ๊ณ  ๋งํ•ด์ฃผ๋Š” ์ž‘์—…์ด ํ•„์š”ํ•˜๋‹ค.

Query Retention

์ฟผ๋ฆฌ๋ฅผ ์œ ์ง€ํ•œ๋‹ค๋Š” ๊ฒƒ์€ Relay์—๊ฒŒ ์ฟผ๋ฆฌ์™€ ์ฟผ๋ฆฌ์— ๊ด€๋ จ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ์ง€์šฐ์ง€ ๋ง์•„๋‹ฌ๋ผ๊ณ  ์–˜๊ธฐํ•˜๋Š”๊ฒƒ๊ณผ ๊ฐ™๋‹ค. ํ•˜๋‚˜ ์ด์ƒ์˜ caller๊ฐ€ ์žˆ๋‹ค๋ฉด ์ฟผ๋ฆฌ๋Š” store์—์„œ ์ง€์›Œ์ง€์ง€ ์•Š๊ฒŒ ๋œ๋‹ค.

๊ธฐ๋ณธ์ ์œผ๋กœ, ์ฟผ๋ฆฌ ์ปดํฌ๋„ŒํŠธ๋Š” useQueryLoader ๋‚˜ usePreloadQuery, ํ˜น์€ ๋‹ค๋ฅธ API๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. ์ฟผ๋ฆฌ ์ปดํฌ๋„ŒํŠธ๋Š” mount ๋œ ์ดํ›„ ์ฟผ๋ฆฌ๋ฅผ ์œ ์ง€ํ•˜๊ณ , unmount ๋œ ์ดํ›„ ์ฟผ๋ฆฌ๋ฅผ ๋†“์•„์ค€๋‹ค. ์ฆ‰ unmount ์ดํ›„์—๋Š” ์–ธ์ œ๋ผ๋„ store์—์„œ ์ฟผ๋ฆฌ์™€ ์ฟผ๋ฆฌ ๊ด€๋ จ ๋ฐ์ดํ„ฐ๋“ค์ด ์‚ญ์ œ๋  ์ˆ˜ ์žˆ๋‹ค.

๋งŒ์•ฝ ์ปดํฌ๋„ŒํŠธ ์ƒ๋ช…์ฃผ๊ธฐ์™€ ๊ด€๊ณ„ ์—†์ด ์ฟผ๋ฆฌ๋ฅผ ์œ ์ง€ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด, retain ๋ฉ”์†Œ๋“œ๋ฅผ ์ด์šฉํ•˜๋ฉด ๋œ๋‹ค.

// Retain query; this will prevent the data for this query and
// variables from being garbage collected by Relay
const disposable = environment.retain(queryDescriptor);

// Disposing of the disposable will release the data for this query
// and variables, meaning that it can be deleted at any moment
// by Relay's garbage collection if it hasn't been retained elsewhere
disposable.dispose();
  • retain ๋ฉ”์†Œ๋“œ๋ฅผ ํ†ตํ•ด ์ฟผ๋ฆฌ ์ปดํฌ๋„ŒํŠธ์˜ ์ƒ๋ช…์ฃผ๊ธฐ์™€๋Š” ์ƒ๊ด€ ์—†์ด ์ฟผ๋ฆฌ๋ฅผ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ์ดํ›„์— ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์žฌ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜, ์ง€๊ธˆ์€ ์—†์ง€๋งŒ ๋‚˜์ค‘์— ์ƒ๊ธธ ๊ฐ™์€ ์ปดํฌ๋„ŒํŠธ์˜ ๋‹ค๋ฅธ ์ธ์Šคํ„ด์Šค๊ฐ€ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

  • dispose ๋ฉ”์†Œ๋“œ๋Š” retain ๋ฉ”์†Œ๋“œ์™€ ๋ฐ˜๋Œ€๋กœ ์ž‘๋™ํ•œ๋‹ค. ์–ธ์ œ๋“ ์ง€ garbage collection๊ฐ€ ์ฟผ๋ฆฌ๋ฅผ ์—†์•จ ์ˆ˜ ์žˆ๋‹ค.

Controlling Relayโ€™s Garbage Collection Policy

ํ˜„์žฌ Garbage Collection์„ ์ปจํŠธ๋กค ํ•  ์ˆ˜ ์žˆ๋Š” ์˜ต์…˜์ด ๋‘๊ฐ€์ง€ ์ •๋„ ์žˆ๋‹ค.

  • GC Scheduler

    gcScheduler ๋ผ๋Š” ํ•จ์ˆ˜๋ฅผ Relay Store์— ๋ถ™์—ฌ์„œ Garbage Collection์„ ์Šค์ผ€์ค„๋ง ํ•  ์ˆ˜ ์žˆ๋‹ค.

    // Sample scheduler function
    // Accepts a callback and schedules it to run at some future time.
    function gcScheduler(run: () => void) {
      resolveImmediate(run);
    }
    
    const store = new Store(source, {gcScheduler});
    • ์›๋ž˜๋Š” ์ƒˆ Store๋ฅผ ์ƒ์„ฑํ•  ๋•Œ gcScheduler ๋ฅผ ๊ฐ™์ด ์ฃผ์ง€ ์•Š๋Š”๋‹ค. ๊ทธ๋ž˜์„œ Relay๋Š” resolveImmediate() ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด garbage collection์„ ์ˆ˜ํ–‰.

      • resolveImmediate๋Š” ์ฐธ์กฐ๊ฐ€ ๋Š์–ด์กŒ์„ ๋•Œ ๋ฐ”๋กœ garbage collection์ด ์ˆ˜ํ–‰๋˜๋„๋ก ํ•˜๋Š” ์ •์ฑ….

      • ๊ทธ๋ž˜์„œ ์ผ๋‹จ ์œ„ ์ฝ”๋“œ๋Š” ์‚ฌ์‹ค์ƒ gcScheduler ์˜ต์…˜์„ ์ฃผ์ง€ ์•Š์€๊ฒƒ๊ณผ ๊ฐ™์Œ.

    • scheduler function์„ ํ†ตํ•ด garbage collection์ด ๊ธฐ๋ณธ ์˜ต์…˜๋ณด๋‹ค ๋œ ๊ณต๊ฒฉ์ ์œผ๋กœ ์ˆ˜ํ–‰๋˜๋„๋ก ์ž‘์„ฑํ•  ์ˆ˜๋„ ์žˆ์Œ. ์‹œ๊ฐ„์ด๋‚˜ scheduler ์†์„ฑ์ด๋‚˜ ๊ทธ ์™ธ์— ๋‹ค๋ฅธ ํœด๋ฆฌ์Šคํ‹ฑ๋“ค์„ ์ด์šฉํ•˜๋ฉด ๋จ.

      • ํ•จ์ˆ˜์˜ ๊ตฌํ˜„๋ถ€์—์„œ run ์ฝœ๋ฐฑ์„ ์ฆ‰์‹œ ์‹คํ–‰ํ•˜๋ฉด ์•ˆ๋จ.

Garbage Collector Buffer Size

Relay Store๋Š” ๋‚ด๋ถ€์ ์œผ๋กœ release buffer๋ฅผ ๊ฐ–๊ณ  ์žˆ๋‹ค. ์ฟผ๋ฆฌ ์œ ์ง€๋ž‘์€ ์ƒ๊ด€ ์—†์ด ๋ช‡ ๊ฐœ์˜ ์ฟผ๋ฆฌ๋ฅผ ์ž„์‹œ๋กœ ์ €์žฅํ•œ๋‹ค. (๋ช‡ ๊ฐœ์˜ ์ฟผ๋ฆฌ๋ฅผ ์ €์žฅํ• ์ง€๋Š” ์กฐ์ ˆ์ด ๊ฐ€๋Šฅ) ์ฟผ๋ฆฌ๋ฅผ ์›๋ž˜ ์†Œ์œ ํ•˜๋˜ ์ฟผ๋ฆฌ ์ปดํฌ๋„ŒํŠธ๊ฐ€ unmount ๋˜๋Š” ๋“ฑ์˜ ์ด์œ ๋กœ ์ฟผ๋ฆฌ๊ฐ€ ์—†์–ด์ง€๋”๋ผ๋„ ์ผ๋‹จ์€ release buffer์— ๋‚จ๋Š”๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์ด์ „ ํŽ˜์ด์ง€๋กœ ๋Œ์•„๊ฐ€๊ฑฐ๋‚˜ ์ด์ „ ํƒญ์œผ๋กœ ๋Œ์•„๊ฐˆ ๋•Œ ๋ฐ์ดํ„ฐ๋ฅผ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

Relay Store์— gcReleaseBufferSize ์˜ต์…˜์„ ์ฃผ๋ฉด release buffer์˜ ์‚ฌ์ด์ฆˆ๋ฅผ ์กฐ์ ˆํ•  ์ˆ˜ ์žˆ๋‹ค.

const store = new Store(source, { gcReleaseBufferSize: 10 });
  • ์œ„ ์ฝ”๋“œ๋Š” ReleaseBuffer์˜ ํฌ๊ธฐ๋ฅผ 10์œผ๋กœ ํ•˜๊ฒ ๋‹ค๋Š” ๋œป. ๊ธฐ๋ณธ๊ฐ’์ด 10์ด๊ธฐ ๋•Œ๋ฌธ์— ์—ฌ๊ธฐ์„œ๋Š” ์‚ฌ์‹ค์ƒ ๋ฒ„ํผ ํฌ๊ธฐ๋ฅผ ๋ฐ”๊พธ์ง€ ์•Š์•˜์Œ.

  • ๋ฒ„ํผ ํฌ๊ธฐ๋ฅผ 0์œผ๋กœ ํ•˜๋ฉด release buffer๋ฅผ ์•ˆ์“ฐ๊ฒ ๋‹ค๋Š” ๋œป๊ณผ ๊ฐ™์Œ. ์ฟผ๋ฆฌ๋“ค์€ ์ฆ‰์‹œ release ๋˜๊ณ  ์žฌ์‚ฌ์šฉ๋  ์ˆ˜ ์—†์„ ๊ฒƒ.

Staleness of Data

๊ธฐ๋ณธ์ ์œผ๋กœ, Relay๋Š” store์— ์žˆ๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ ๋‚ก์•˜์„ ๊ฒƒ์ด๋ผ๋Š” ๊ฐ€์ •์„ ํ•˜์ง€ ์•Š๋Š”๋‹ค. ๋ฐ์ดํ„ฐ ๋ฌดํšจํ™” API๋ฅผ ํ†ตํ•ด ๋ช…์‹œ์ ์œผ๋กœ ๋งˆํ‚นํ•ด์ฃผ๊ฑฐ๋‚˜ ์ฟผ๋ฆฌ ์บ์‹œ ๋งŒ๋ฃŒ ์‹œ๊ฐ„๋ณด๋‹ค ์˜ค๋ž˜ ์ง€๋‚œ ๊ฒฝ์šฐ๊ฐ€ ์•„๋‹ˆ๋ผ๋ฉด Relay๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๋‚ก์•˜๋‹ค๊ณ  ์ƒ๊ฐํ•˜์ง€ ์•Š์„ ๊ฒƒ์ด๋‹ค.

๋ฐ์ดํ„ฐ๊ฐ€ ๋‚ก์•˜๋‹ค๋Š”๊ฑธ ํ™•์‹คํžˆ ์•Œ ๋•Œ๋Š” ๋งˆํ‚น์„ ํ•ด์ฃผ๋Š”๊ฒŒ ์ข‹๋‹ค. ๋” ์ด์ƒ์˜ mutation์ด ์ผ์–ด๋‚˜์ง€ ์•Š์Œ์„ ๋ณด์žฅํ•  ์ˆ˜ ์žˆ์„ ๋•Œ๊ฐ€ ๊ทธ๋ ‡๋‹ค.

Relay๋Š” ์•„๋ž˜์™€ ๊ฐ™์€ API๋“ค์„ ์ œ๊ณตํ•˜๊ณ  ์ด๊ฑธ ์ด์šฉํ•ด store์— ์žˆ๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ ๋‚ก์•˜์Œ์„ ํ‘œ์‹œํ•  ์ˆ˜ ์žˆ๋‹ค.

Globally Invalidating the Relay Store

์กฐ๊ธˆ ๊ณผ๊ฒฉํ•œ ๋ฐฉ๋ฒ•์€ store์— ์žˆ๋Š” ๋ชจ๋“  ์ฟผ๋ฆฌ ์บ์‹œ๋ฅผ ๋ฌดํšจํ™”ํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ์ด๋ ‡๊ฒŒ ์ „๋ถ€๋ฅผ ๋ฌดํšจํ™”ํ•˜๋ฉด Relay๋Š” ํ˜„์žฌ ์บ์‹ฑ๋œ ๋ฐ์ดํ„ฐ๋“ค์„ ์ „๋ถ€ ๋‚ก์•˜๋‹ค๊ณ  ์ธ์‹ํ•˜๊ฒŒ ๋œ๋‹ค.

function updater(store) {
	store.invalidateStore();
}

์ด๋ ‡๊ฒŒ invalidateStore() ๋ฉ”์†Œ๋“œ๋ฅผ ํ†ตํ•ด ์ „์ฒด store์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฌดํšจํ™” ํ•  ์ˆ˜ ์žˆ๋‹ค.

  • ๋ฌดํšจํ™”๋œ ๋ฐ์ดํ„ฐ๋“ค์€ ๋‹ค์Œ์— ์ ‘๊ทผํ•ด ํ‰๊ฐ€ํ•˜๋ ค ํ•  ๋•Œ ๋„คํŠธ์›Œํฌ๋กœ๋ถ€ํ„ฐ refetch.

  • updater ํ•จ์ˆ˜๋Š” mutation, subscription, ํ˜น์€ ๋กœ์ปฌ store๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๋Š” ๋กœ์ง์˜ ์ผ๋ถ€๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Œ.

Invalidating Specific Data In The Store

์กฐ๊ธˆ ๋” ๊ตฌ์ฒด์ ์œผ๋กœ, ์–ด๋–ค ๋ฐ์ดํ„ฐ๋ฅผ ๋ฌดํšจํ™” ํ•˜๊ฑฐ๋‚˜ ํ˜น์€ store์— ์žˆ๋Š” ์–ด๋–ค ํŠน์ •ํ•œ ๋ ˆ์ฝ”๋“œ๋งŒ ๋ฌดํšจํ™” ํ•˜๋Š” ๊ฒƒ๋„ ๊ฐ€๋Šฅํ•˜๋‹ค. ๋ฐ”๋กœ ์œ„์˜ global invalidating์ฒ˜๋Ÿผ store ์ „๋ถ€๋ฅผ ๋ฌดํšจํ™”ํ•˜์ง€ ์•Š๊ณ  ์ง€์ •๋œ ์ฟผ๋ฆฌ๋“ค๋งŒ ๋ฌดํšจํ™”๋œ๋‹ค.

function updater(store) {
	const user = store.get('<id>');
	if(user != null) {
		user.invalidateRecord();
	}
}
  • invalidateRecord() ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉ. invalidateStore๊ณผ๋Š” ๋‹ค๋ฅด๊ฒŒ store์˜ ์ผ๋ถ€ ๋ฐ์ดํ„ฐ(user)๋งŒ ๋ฌดํšจํ™”. ์ด๋ ‡๊ฒŒ ๋˜๋ฉด user ๋ ˆ์ฝ”๋“œ๋Š” ๋‚ก์•˜๋‹ค๊ณ  ๋งˆํ‚น๋˜์–ด ๋‹ค์Œ์— ์ ‘๊ทผํ•ด ํ‰๊ฐ€ํ•˜๋ ค ํ•  ๋•Œ๋Š” ๋„คํŠธ์›Œํฌ๋กœ๋ถ€ํ„ฐ refetch ๋  ๊ฒƒ.

  • ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ updater ํ•จ์ˆ˜๋Š” mutation, subscription, ํ˜น์€ ๋กœ์ปฌ store๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๋Š” ๋กœ์ง์˜ ์ผ๋ถ€๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Œ.

Subscribing to Data Invalidation

์œ„์—์„œ โ€˜๋งˆํ‚นํ•œ๋‹คโ€™๋Š” ํ‘œํ˜„์„ ์‚ฌ์šฉํ–ˆ๋Š”๋ฐ, ๋งˆํ‚น์„ ํ•˜๋ฉด ๋‹ค์Œ ํ‰๊ฐ€ ์‹œ์ ์— refetch ํ•˜๊ณ  ์ด๋ ‡๊ฒŒ ๋‹ค์‹œ ๊ฐ€์ ธ์™€์ง„ ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋Š” ํŠน์ง•์ด ์žˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ํŽ˜์ด์ง€ ๋’ค๋กœ๊ฐ€๊ธฐ๋ฅผ ํ•œ๋‹ค๋ฉด ๋‚ก์€ ์ฟผ๋ฆฌ๋ฅผ ๋ Œ๋”๋งํ•˜๋ ค ํ•  ๊ฒƒ์ด๊ณ , Relay๋Š” ๋‚ก์€ ์ฟผ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ๋„คํŠธ์›Œํฌ๋กœ๋ถ€ํ„ฐ refetchํ•ด์„œ ๊ฐ€์ ธ์˜จ ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•  ๊ฒƒ์ด๋‹ค.

์ด๋Ÿฐ ๋งˆํ‚น์€ ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ ์œ ์šฉํ•˜์ง€๋งŒ, ๊ฐ€๋”์€ ๋ฌดํšจํ™” ์—ฌ๋ถ€๋ž‘์€ ์ƒ๊ด€์—†์ด ์ฆ‰์‹œ refetchํ•ด์•ผ ํ•  ๋•Œ๊ฐ€ ์žˆ๋‹ค.

  • ๋งŒ์•ฝ ์ง€๊ธˆ ์žˆ๋Š” ํŽ˜์ด์ง€์˜ ์ฟผ๋ฆฌ๊ฐ€ ๋‚ก์€ ์ฟผ๋ฆฌ๋ผ๋ฉด, ์ผ๋ถ€ ๋ฐ์ดํ„ฐ๋Š” ์—…๋ฐ์ดํŠธ๊ฐ€ ํ•„์š”. ๊ทธ๋ƒฅ ๋งˆํ‚นํ•˜๋Š”๊ฒƒ ๋งŒ์œผ๋กœ๋Š” ์ฆ‰์‹œ ์ƒˆ๋กœ์šด ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค์ง€๋„ ์•Š์„๊ฑฐ๊ณ  ๋‚ก์€ ๋ฐ์ดํ„ฐ๋ฅผ ์ƒˆ๋กœ์šด ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด์—ฌ์ค„ ์ˆ˜ ์—†์Œ.

  • ์ด์ „ ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•˜๊ธด ํ•ด๋„ ์ด์ „ ํŽ˜์ด์ง€๊ฐ€ unmount๋˜์ง€ ์•Š์•˜๋‹ค๋ฉด ์ด์ „ ํŽ˜์ด์ง€์˜ ๋ทฐ๊ฐ€ ๋‹ค์‹œ ํ‰๊ฐ€๋˜์ง€๋„ ์•Š์„ ๊ฒƒ์ด๊ณ , ๋”ฐ๋ผ์„œ ๋‚ก์€ ๋ฐ์ดํ„ฐ๋ผ๋„ ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉํ•˜๊ฒŒ ๋  ๊ฒƒ์ด๋‹ค.

์ด๋Ÿฐ ์ƒํ™ฉ๋“ค์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— Relay๋Š” useSubscribeToInvalidationState ๋ผ๋Š” ํ›…์„ ์ œ๊ณตํ•œ๋‹ค.

function ProfilePage(props) {
  // Example of querying data for the current page for a given user
  const data = usePreloadedQuery(
    graphql`...`,
    props.preloadedQuery,
  )

  // Here we subscribe to changes in invalidation state for the given user ID.
  // Whenever the user with that ID is marked as stale, the provided callback will
  // be executed
  useSubscribeToInvalidationState([props.userID], () => {
    // Here we can do things like:
    // - re-evaluate the query by passing a new preloadedQuery to usePreloadedQuery.
    // - imperatively refetch any data
    // - render a loading spinner or gray out the page to indicate that refetch
    //   is happening.
  })

  return (...);
}
  • ์—ฌ๊ธฐ์„œ useSubscribeInvalidationState ํ›…์€ ์ธ์ž๋กœ id๋“ค์ด ๋‹ด๊ธด ๋ฐฐ์—ด์„ ๋ฐ›๊ณ , ์ฝœ๋ฐฑ๋„ ํ•˜๋‚˜ ๋ฐ›๋Š”๋‹ค. ์ € ๋ฐฐ์—ด์— ๋‹ด๊ธด id๋“ค ์ค‘ ํ•˜๋‚˜๋ผ๋„ ๋‚ก์€ ๋ฐ์ดํ„ฐ๋ผ๊ณ  ๋งˆํ‚น๋œ๋‹ค๋ฉด ์ฝœ๋ฐฑ์ด ํ˜ธ์ถœ๋œ๋‹ค.

  • ์ฝœ๋ฐฑ ์•ˆ์—์„œ๋Š” refetch ํ•˜๊ฑฐ๋‚˜ ๋‚ก์€ ๋ฐ์ดํ„ฐ์— ์˜์กดํ•˜๋Š” ํ˜„์žฌ์˜ ๋ทฐ๋ฅผ ์—…๋ฐ์ดํŠธํ•  ์ˆ˜ ์žˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค๋ฉด top-level์— ์žˆ๋Š” usePreloadedQuery ๋ฅผ ํ˜ธ์ถœํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ์ตœ์‹  ์ƒํƒœ๋กœ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค. usePreloadedQuery ๋Š” ๋‚ก์€ ์ฟผ๋ฆฌ๋ฅผ ํฌํ•จํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๋‹น์—ฐํžˆ refetch๋˜๊ณ  store ์บ์‹œ๋„ ์—…๋ฐ์ดํŠธ ๋  ๊ฒƒ์ด๋‹ค.

Query Cache Expiration Time

์บ์‹ฑ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ง€๊ณ  ์–ด๋–ค operation์„ ์ˆ˜ํ–‰ํ•˜๋Š”๋ฐ๋Š” โ€˜์ฟผ๋ฆฌ ์บ์‹œ ๋งŒ๋ฃŒ ์‹œ๊ฐ„โ€™๋„ ์˜ํ–ฅ์„ ์ค€๋‹ค.

  • ์ฟผ๋ฆฌ ์บ์‹œ ๋งŒ๋ฃŒ ์‹œ๊ฐ„ ์ดํ›„๋กœ ์ƒˆ๋กญ๊ฒŒ fetch๋˜์ง€ ์•Š์€ ์ฟผ๋ฆฌ์ด๊ฑฐ๋‚˜

  • ์ฟผ๋ฆฌ๊ฐ€ ํฌํ•จํ•˜๋Š” ๋ ˆ์ฝ”๋“œ๋“ค ์ค‘ ์ ์–ด๋„ ํ•˜๋‚˜๊ฐ€ ๋ฌดํšจํ™”๋œ ๋ ˆ์ฝ”๋“œ์ผ ๊ฒฝ์šฐ

๊ทธ๋ฆฌ๊ณ  store์— ์žˆ๋Š” ๋ ˆ์ฝ”๋“œ๋“ค๋กœ๋งŒ ์ฟผ๋ฆฌ๋ฅผ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์„ ๋•Œ ์ด๋ฅผ ์˜ค๋ž˜๋œ ์ฟผ๋ฆฌ๋ผ๊ณ  ํ•œ๋‹ค.

์ฟผ๋ฆฌ๊ฐ€ ๋‚ก์•˜๋Š”์ง€๋Š” ์ƒˆ๋กœ์šด request๊ฐ€ ๋งŒ๋“ค์–ด์กŒ์„ ๋•Œ ํŒ๋‹จํ•œ๋‹ค. loadQuery ๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ๊ฐ€ ๊ทธ๋ ‡์ฃ . ์˜ค๋ž˜๋œ ๋ฐ์ดํ„ฐ๋ผ๋„ ์ด๋ฅผ ์ฐธ์กฐํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ์— ์˜ํ•ด ๊ณ„์† ๋ Œ๋”๋ง๋  ์ˆ˜ ์žˆ๋‹ค. ํ•˜์ง€๋งŒ ์˜ค๋ž˜๋œ ๋ฐ์ดํ„ฐ๋ฅผ ์ด์šฉํ•ด ๋งŒ๋“ค์–ด์ง„ ์ถ”๊ฐ€ ์š”์ฒญ์€ ๋„คํŠธ์›Œํฌ๋ฅผ ํ†ตํ•ด ์ƒˆ๋กœ์šด ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„์˜จ๋‹ค.

const store = new Store(source, { queryCacheExpirationTime : 5 * 60 * 1000 });

์ฟผ๋ฆฌ ์บ์‹œ ๋งŒ๋ฃŒ์‹œ๊ฐ„ ์—ญ์‹œ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ Store๋ฅผ ์ƒ์„ฑํ•  ๋•Œ ์˜ต์…˜์œผ๋กœ ์ค„ ์ˆ˜ ์žˆ๋‹ค.

์ฟผ๋ฆฌ ์บ์‹œ ๋งŒ๋ฃŒ์‹œ๊ฐ„ ์˜ต์…˜์„ ๋”ฐ๋กœ ์ฃผ์ง€ ์•Š์œผ๋ฉด ๋‚ก์€ ์ฟผ๋ฆฌ์ธ์ง€ ๊ฒ€์‚ฌํ•˜๋Š” ์ž‘์—…์€ ์ฐธ์กฐ๋œ ๋ ˆ์ฝ”๋“œ๊ฐ€ ๋ฌดํšจํ™”๋˜์—ˆ๋Š”์ง€ ์—ฌ๋ถ€๋งŒ ์ฒดํฌํ•œ๋‹ค. ๋งŒ๋ฃŒ์‹œ๊ฐ„์ด ๋”ฐ๋กœ ์ง€์ •๋˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๋œป์ด๋‹ค.

Last updated