API

λ°˜λ³΅λ˜λŠ” API Call

  • 자주 λ³€κ²½λ˜μ§€ μ•ŠλŠ” APIλŠ” μΊμ‹±ν•΄μ„œ μ‚¬μš©ν•˜λ©΄ API 호좜 λΉ„μš©κ³Ό μ‘λ‹΅μ‹œκ°„μ„ μ΅œμ ν™”ν•  수 μžˆλ‹€.

  • 자주 λ³€κ²½λ˜λŠ” API도 캐싱을 μ‚¬μš©ν•œλ‹€λ©΄ 호좜 λΉ„μš©μ€ λ°œμƒν•˜μ§€λ§Œ μΊμ‹±λœ 데이터λ₯Ό λ¨Όμ € 보여주고 λ°±κ·ΈλΌμš΄λ“œμ—μ„œ APIλ₯Ό ν˜ΈμΆœν•˜μ—¬ κ°±μ‹ ν•΄μ€€λ‹€λ©΄ μ‘λ‹΅μ‹œκ°„ 츑면의 μ΄λ“μœΌλ‘œ 인해 μœ λ €ν•œ μ‚¬μš©μž κ²½ν—˜μ„ μ œκ³΅ν•΄μ€„ 수 μžˆλ‹€.

Prefetching

pre-fetch, λ Œλ”λ§ 이전에 데이터λ₯Ό 미리 받아놓기

Client Side Prefetching

  • router-prefetch β†’ 이동할 λΌμš°ν„°μ˜ νŽ˜μ΄μ§€ 데이터λ₯Ό 미리 fetching

  • client side의 transition을 λΉ λ₯΄κ²Œ ν•˜κΈ° μœ„ν•¨

  • next/link λŠ” μžλ™μœΌλ‘œ prefetching

  • next/link 의 <Link/> λ₯Ό μ‚¬μš©ν•˜μ§€ μ•ŠλŠ” κ²½μš°μ— μœ μ˜λ―Έν•˜λ‹€.

const router = useRouter(); 

useEffect(() => {
  router.prefetch('/dashboard')
}, [router])

Server Side Prefetching

  • λ Œλ”λ§μ— ν•„μš”ν•œ 데이터λ₯Ό 미리 μ„œλ²„μ—μ„œ fetch ν•˜μ—¬ λ Œλ”λ§ μ‹œ λ°”λ‘œ 보여쀄 수 μžˆλ„λ‘ 제곡

  • initialData prop β†’ getServerSideProps, getStaticProps 등을 μ΄μš©ν•˜μ—¬ μ„œλ²„ dataλ₯Ό 미리 fetchingν•˜κ³  props둜 λ„˜κ²¨ useQuery의 initialData둜 λ„˜κ²¨μ£ΌλŠ” 방식

    • 단점 β†’ useQueryλ₯Ό μ‚¬μš©ν•˜λŠ” μ»΄ν¬λ„ŒνŠΈκΉŒμ§€ props둜 λ„˜κ²¨μ£Όμ–΄μ•Ό ν•˜λ―€λ‘œ props driling이 심해지고 refetching μ‹œμ μ„ λ”°λ‘œ μž‘μ„±ν•΄μ£Όμ–΄μ•Ό ν•œλ‹€.

export const getStaticProps = async() => {
  const posts = await getPosts();
  return {props: { posts }}
}

const Posts = ({ posts  }) => {
  const { data } = useQuery({
    queryKey: ['posts'],
    queryFn: getPosts,
    initialData: posts
   })
}
  • hydration prefetching β†’ λ§ˆμ°¬κ°€μ§€λ‘œ getServerSideProps, getStaticProps 을 μ΄μš©ν•˜μ—¬ μ„œλ²„μ—μ„œ fetchingν•œ 데이터λ₯Ό queryClient에 λ‹΄μ•„ dehydrateState둜 λ„˜κ²¨μ£Όκ³  <Hydrate /> HOC둜 μ „λ‹¬ν•œλ‹€.

    • Hydrate HOCλŠ” 받은 stateλ₯Ό client의 queryClient둜 셋업을 μ§„ν–‰ν•œλ‹€.

    • ν•΄λ‹Ή λ°μ΄ν„°λŠ” useQueryμ—μ„œ stale data둜 μ·¨κΈ‰λ˜μ–΄ λ Œλ”λ§μ΄ μš°μ„  μ§„ν–‰λ˜κ³  λ°±κ·ΈλΌμš΄λ“œμ—μ„œ μ΅œμ‹ λ°μ΄ν„°λ₯Ό refetch λ°›μ•„ ꡐ체해쀀닀.

Caching

  • Stale β†’ 이전에 fetch된 μ‹ μ„ ν•˜μ§€ μ•Šμ€ 데이터

    • μ‹ μ„ ν•˜μ§€ μ•Šμ€ 데이터λ₯Ό μš°μ„  보여주고 λ°±κ·ΈλΌμš΄λ“œμ—μ„œ μ΅œμ‹  데이터λ₯Ό λ¦¬νŒ¨μΉ­ν•˜λŠ” 과정이 μ§„ν–‰λœλ‹€.

    • stale time(default 0s) 만큼 fresh μƒνƒœλ‘œ μ‘΄μž¬ν•˜λ‹€κ°€ stale μƒνƒœλ‘œ 변경됨

    • stale μƒνƒœμ—μ„  νŠΉμ • Refetching 쑰건 μΆ©μ‘±μ‹œ λ°±κ·ΈλΌμš΄λ“œμ—μ„œ refetching 과정이 일어남

      • μƒˆ QueryInstanceκ°€ 마운트 될 λ•Œ (νŽ˜μ΄μ§€ 이동)

      • λΈŒλΌμš°μ € νƒ­ focus out/in μ „ν™˜ μ‹œ

      • λ„€νŠΈμ›Œν¬κ°€ μž¬μ—°κ²° 될 λ•Œ

      • refetchInterval μ„€μ • μ‹œ

  • Cache β†’ fetch λ˜μ–΄ μž¬μ‚¬μš©λ˜λŠ” 데이터

    • cache time(default 5m)λ™μ•ˆ μ €μž₯λœλ‹€.

    • QueryCache λ‚΄λΆ€ queries에 데이터가 μ‘΄μž¬ν•˜λŠ” μƒνƒœ

Persist Caching

  • λ©”λͺ¨λ¦¬ μƒνƒœκ°€ μ•„λ‹Œ λΈŒλΌμš°μ € λ‚΄ μŠ€ν† λ¦¬μ§€μ— μΊμ‹±λœ 데이터λ₯Ό μ €μž₯ν•˜μ—¬ νŽ˜μ΄μ§€λ₯Ό μƒˆλ‘œκ³ μΉ¨ν•΄λ„ refetching ν•˜μ§€ μ•Šκ³  이전에 μ €μž₯된 데이터λ₯Ό μ‚¬μš©ν•  수 μžˆλ„λ‘ λ§Œλ“€ 수 μžˆλ‹€.

if (typeof window === 'undefined') {
  return (
    <QueryClientProvider client={queryClient}>
      <Component {...pageProps} />
    </QueryClientProvider>
  )
}

return (
  <PersistQueryClientProvider 
    client={queryClient}
    persistOptions={{
      persister: createSyncStoragePersister({
        storage: window.localStorage // or window.sessionStorage
      })
    }}
  >
    <Hydrate state={state}>
      <Component {...pageProps} />
    </Hydrate>
  </QueryClientProvider>
)

Last updated