[TIL] SWR(stale-while-revalidate)

๊น€๋•…์ฃผยท2022๋…„ 3์›” 16์ผ
0

TIL

๋ชฉ๋ก ๋ณด๊ธฐ
26/33
post-custom-banner

๐Ÿ’ปSWR?


โœ… ๊ณต์‹๋ฌธ์„œ

SWR์€ ๋จผ์ € ์บ์‹œ๋กœ๋ถ€ํ„ฐ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ˜ํ™˜ํ•œ ํ›„, fetch ์š”์ฒญ(์žฌ๊ฒ€์ฆ)์„ ํ•˜๊ณ , ์ตœ์ข…์ ์œผ๋กœ ์ตœ์‹ ํ™”๋œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ์ „๋žต์ด๋‹ค.

์ฆ‰, axios๋‚˜ fetch๋กœ ๋ฐ›์•„์˜จ ๋ฐ์ดํ„ฐ๊ฐ€ ์บ์‹ฑ๋˜๊ณ  ๋‹ค์‹œ ๋ฐ์ดํ„ฐ๋ฅผ ์š”์ฒญํ•  ๋•Œ ๋ถˆํ•„์š”ํ•œ ์š”์ฒญ์„ ํ•˜์ง€ ์•Š๊ณ  ์บ์‹ฑ๋œ ๊ฐ’์„ ์‚ฌ์šฉํ•œ๋‹ค! ๋ผ๊ณ  ์ดํ•ดํ–ˆ๋‹ค. SWR์˜ ๋นŒํŠธ์ธ ์บ์‹ฑ๊ณผ ์ค‘๋ณต์ œ๊ฑฐ๋Š” ๋ถˆํ•„์š”ํ•œ ๋„คํŠธ์›Œํฌ ์š”์ฒญ์„ ์ค„์—ฌ์ค€๋‹ค.


useSWR ์˜ต์…˜

const { data, error, isValidating, mutate } = useSWR(key, fetcher, options)

ํŒŒ๋ผ๋ฏธํ„ฐ

  • key : ์š”์ฒญ์„ ์œ„ํ•œ ๊ณ ์œ ํ•œ ํ‚ค ๋ฌธ์ž์—ด(ํ•จ์ˆ˜ ,๋ฐฐ์—ด, null ๋„ ๊ฐ€๋Šฅ)
  • fetcher : (์˜ต์…˜) ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๊ธฐ ์œ„ํ•œ ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” Promise
  • options : (์˜ต์…ฅ) SWR hook์„ ์œ„ํ•œ ์˜ต์…˜ ๊ฐ์ฒด

๋ฐ˜ํ™˜ ๊ฐ’

  • data : fetcher๊ฐ€ ํ‚ค๋ฅผ ์ธ์ž๋กœ ๋ฐ›์•„ ์ดํ–‰ํ•œ data(๋กœ๋“œ๋˜์ง€ ์•Š์œผ๋ฉด undefined)
  • error : fetcher๊ฐ€ ๋˜์ง„ ์—๋Ÿฌ(๋˜๋Š” undefined)
  • isValidating : ์š”์ฒญ์ด๋‚˜ ๊ฐฑ์‹  ์—ฌ๋ถ€
  • mutate : ์บ์‹œ ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฎคํ…Œ์ดํŠธํ•˜๊ธฐ ์œ„ํ•œ ํ•จ์ˆ˜

mutate?

mutate(key)๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ๋™์ผํ•œ ํ‚ค๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋‹ค๋ฅธ SWR hook์—๊ฒŒ ๊ฐฑ์‹  ๋ฉ”์‹œ์ง€๋ฅผ ์ „์—ญ์œผ๋กœ ๋ธŒ๋กœ๋“œ ์บ์ŠคํŒ…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊นŒ์ง€๊ฐ€ ๊ณต์‹๋ฌธ์„œ์— ๋‚˜์™€ ์žˆ๋Š” ๋‚ด์šฉ์ด๋‹ค.
๋‚ด๊ฐ€ ์ดํ•ดํ•œ ๋‚ด์šฉ์€ ์˜ˆ๋ฅผ๋“ค์–ด mutate("/api/user")๋ผ๋ฉด "/api/user"๋ฅผ ๊ฐ–๊ณ ์žˆ๋Š” ๋™์ผํ•œ hook์—๊ฒŒ ๊ฐฑ์‹  ๋ฉ”์„ธ์ง€๋ฅผ ๋ณด๋‚ธ๋‹ค.

๐Ÿคทโ€โ™€๏ธ ๋‚ด๊ฐ€ ์ดํ•ดํ•œ mutate post ๋ฐฉ๋ฒ•

์ตœ์‹  ๋ฐ์ดํ„ฐ๋กœ ๋กœ์ปฌ ์—…๋ฐ์ดํŠธ -> ์—…๋ฐ์ดํŠธ ๋‚ด์šฉ์„ ๋ฆฌ๋ชจํŠธ ๋ฐ์ดํ„ฐ ์ˆ˜์ •ํ•˜๊ธฐ ์œ„ํ•ด post์š”์ฒญ -> ๋ฆฌ๋ชจํŠธ ๋ฐ์ดํ„ฐ์—์„œ ๊ฐ€์ ธ์˜จ ์ •๋ณด๋กœ ๊ฐฑ์‹ ํ•จ(์ตœ์‹ ๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์˜ด)

์ด๋Ÿฐ์‹์œผ๋กœ ๋กœ์ปฌ๊ณผ ๋ฆฌ๋ชจํŠธ์— ์—…๋ฐ์ดํŠธ๋ฅผ ํ•˜๋ฉด ํด๋ผ์ด์–ธํŠธ ์ž…์žฅ์—์„  ๋น ๋ฅด๊ฒŒ ๋Š๊ปด์งˆ ๊ฒƒ์ด๋‹ค...!

ํ•˜์ง€๋งŒ ๋งŽ์€ POST API๋“ค์€ ์—…๋ฐ์ดํŠธ ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ์ง์ ‘ ๋ฐ˜ํ™˜ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋‹ค์‹œ ๊ฐฑ์‹ ํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค.

mutate("api", nuwUser, false) // ๋กœ์ปฌ๋ฐ์ดํ„ฐ๋งŒ ์—…๋ฐ์ดํŠธํ•˜๊ณ  ๋žœ๋”

๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์˜ค๊ธฐ ์˜ˆ์ œ

export const fetcher = (...args) => fetch(...args).then(res => res.json())

import useSWR from "swr"

function Profile(){
	const {data, error} = useSWR("API URL", fetcher); ///api url๊ณผ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋น„๋™๊ธฐ ํ•จ์ˆ˜๊ฐ€ ๋“ค์–ด์˜ฌ ์ˆ˜ ์žˆ๋‹ค.ex) fetch, Axios
  
  if (error) return <div>failed to load</div>
  if (!data) return <div>loading...</div>
  
}

์ด ์˜ˆ์ œ์—์„œ useSWR hook์€ key๋ฌธ์ž์—ด๊ณผ fetcherํ•จ์ˆ˜๋ฅผ ๋ฐ›๋Š”๋‹ค.

key๋Š” ๋ฐ์ดํ„ฐ์˜ ๊ณ ์œ ํ•œ ์‹๋ณ„์ž์ด๋ฉฐ(์ผ๋ฐ˜์ ์œผ๋กœ API URL) fetcher์— ์ธ์ž๋กœ ์ „๋‹ฌ๋œ๋‹ค.


๊ธฐ๋ณธ ์ธ์ž

์ธ์ž

๊ธฐ๋ณธ๊ฐ’์œผ๋กœ key๋Š” ์ธ์ž๋กœ์จ fetcher์— ์ „๋‹ฌ๋œ๋‹ค. ๋‹ค์Œ ์„ธ ๊ฐ€์ง€ ํ‘œํ˜„์‹์€ ๋™์ผํ•˜๋‹ค.


useSWR('url', () => fetcher('/api/user'))
useSWR('url', url => fetcher(url))
useSWR('url', fetcher)

๋‹ค์ค‘ ์ธ์ž

fetcher ํ•จ์ˆ˜์— ์—ฌ๋Ÿฌ ์ธ์ž๋ฅผ ์ „๋‹ฌํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

:: Bad

  • ๋ฐ์ดํ„ฐ ์‹๋ณ„์ž(/api/user)๋Š” ๊ทธ๋Œ€๋กœ์ด๊ณ  token์ด ๋ณ€๊ฒฝ๋˜๋ฉด SWR์€ ์—ฌ์ „ํžˆ ๋™์ผํ•œ ํ‚ค๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ž˜๋ชป๋œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
useSWR('url', url => fetchWithToken(url, token))

:: Good

  • ๋Œ€์‹ ์— ๋ฐฐ์—ด์„ keyํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์‚ฌ์šฉํ•˜์—ฌ fetchWithToken์— ์ธ์ž๋กœ ๋ณด๋‚ผ ์ˆ˜ ์žˆ๋‹ค.

const { data: user } = useSWR(['url', token], fetchWithToken)

์—๋Ÿฌ์ฒ˜๋ฆฌ

fetcher ์•ˆ์—์„œ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ๋‹ค๋ฉด hook์— ์˜ํ•ด error๋กœ ๋ฐ˜ํ™˜๋œ๋‹ค.


export const fetcher = (...args) => fetch(...args).then(res => res.json())

const {data, error} = useSWR("URL", fetcher)

์ž๋™ ๊ฐฑ์‹ 

ํฌ์ปค์Šค ์‹œ์— ์ž๋™๊ฐฑ์‹ 

ํŽ˜์ด์ง€์— ๋‹ค์‹œ ํฌ์ปค์Šคํ•˜๊ฑฐ๋‚˜ ํƒญ์„ ์ „ํ™˜ํ•  ๋•Œ, SWR์€ ๋ฐ์ดํ„ฐ๋ฅผ ์ž๋™ ๊ฐฑ์‹ ํ•œ๋‹ค.

์ฆ‰ ์ตœ์‹  ์ƒํƒœ๋กœ ์ฆ‰์‹œ ๋™๊ธฐํ™”ํ•  ์ˆ˜ ์žˆ๋‹ค.

axios๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„์˜ค๋Š” ๊ฒฝ์šฐ๋Š” ํ†ต์‹ ์ด ๋๋‚˜๊ณ  ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐฑ์‹ ํ•˜์ง€ ์•Š์•˜๋‹ค.


์ธํ„ฐ๋ฒŒ ์‹œ์— ๊ฐฑ์‹ ํ•˜๊ธฐ

SWR์€ ์ž๋™ ๋ฐ์ดํ„ฐ ๋‹ค์‹œ ๊ฐ€์ ธ์˜ค๊ธฐ ์˜ต์…˜์„ ์ œ๊ณตํ•œ๋‹ค. hook๊ณผ ๊ด€๋ จ๋œ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ํ™”๋ฉด์ƒ์— ์žˆ์„ ๋•Œ๋งŒ ๋‹ค์‹œ ๊ฐ€์ ธ์˜ค๊ธฐ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

:: ๊ณ„์†ํ•ด์„œ ์—…๋ฐ์ดํŠธ

profile
์ผ๊ณฑ ๋ฒˆ ๋„˜์–ด์ ธ๋„ ์—ฌ๋Ÿ ๋ฒˆ ์ผ์–ด๋‚˜๋ฉด์„œ ์„ฑ์žฅํ•˜๋Š” ํ”„๋ก ํŠธ ๊ฐœ๋ฐœ์ž์ž…๋‹ˆ๋‹ค
post-custom-banner

0๊ฐœ์˜ ๋Œ“๊ธ€