
๋๊ด์ ์ ๋ฐ์ดํธ๋ก ์ฌ์ฉ์ ๊ฒฝํ ๊ฐ์ ํ๊ธฐ

- #๋๊ด์ ์ ๋ฐ์ดํธ
- #optimistic
- #@tanstack/react-query
- #Jotai
์๋ ํ์ธ์, ๋ ธ๋จธ์ค ํ๋ก ํธ์๋ ํ ๊น๋ฏผ์์ ๋๋ค.
์ด๋ฒ ๊ธ์์๋ ๋๊ด์ ์ ๋ฐ์ดํธ๋ฅผ ์ ์ฉํ์ฌ ์ฌ์ฉ์ ๊ฒฝํ์ ๊ฐ์ ํ ๋ฐฉ์์ ๊ณต์ ํด๋ณด๊ณ ์ ํฉ๋๋ค.
Jotai๋ก ๊ด๋ฆฌ๋๊ณ ์๋ ์๋ฒ ๋ฐ์ดํฐ ์ํ
fromm ์ฑ์ ํฌ๊ณผ ์ํฐ์คํธ๊ฐ ์ํตํ๋ ์ปค๋ฎค๋ํฐ ๊ธฐ๋ฅ์ธ ์ฑ๋ ์๋น์ค๋ฅผ ์ ๊ณตํฉ๋๋ค. ๊ธฐ์กด์๋ ์ฑ๋์ ๋ชจ๋ ๋ฐ์ดํฐ ์ํ๋ฅผ Jotai๋ก ๊ด๋ฆฌํ์ต๋๋ค. ์๋ฅผ ๋ค์ด, ๋ฏธ๋์ด ํฌ์คํธ API๋ฅผ ์์ฒญํด ๋ฐ์ดํฐ๋ฅผ Atom์ ์ ์ฅํ๊ณ , ์ข์์ ๋ฒํผ์ ๋๋ฅด๋ฉด Atom์ ๋ฐ์ดํฐ๋ฅผ ์์ ํด ๋ค์ ๋ฐ์ํ๋ ๋ฐฉ์์ด์์ต๋๋ค. ์ด ๋ฐฉ์์ ์ฌ๋ฌ ์ด์ ๋ ์์์ง๋ง, ๊ฐ์ฅ ํฐ ๋ฌธ์ ๋ ๋ฐ์ดํฐ ์ ํฉ์ฑ ๋ถ์ผ์น์ ์ ์ง๋ณด์ํ๊ธฐ ์ด๋ ค์์ง๋ ์น๋ช ์ ์ธ ๋จ์ ์ด ์์์ต๋๋ค.
์ด๋ก ์ธํด ํ์ํ ์์ ์ ๋งค๋ฒ ์ ์ญ ๋ฐ์ดํฐ๋ฅผ ์ด๊ธฐํํด์ผ ํ๊ณ , ๊ทธ ํ์ด๋ฐ ์ด์๋ก ๊ฒฐ๊ตญ ๋น ๋ฐฐ์ด์ด ๋์ด ๋ฐ์ดํฐ๊ฐ ์์ ๋ณด์ด์ง ์๋ ์ด์๋ฅผ ์ด๋ํ๊ฒ ๋์์ต๋๋ค.์๋ฒ ์๋ต๊ณผ ์๊ด์์ด ์ผ๋จ ํด๋ผ์ด์ธํธ ๊ฐ์ด ๋จผ์ ๋ณ๊ฒฝ๋๋ฉด์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๊ธฐ ๋๋ฌธ์ ๋๋ค. ์๋ฅผ ๋ค์ด, ์ฌ์ฉ์๊ฐ ๋๊ธ ์คํ๋ทฐ์์ โ์ข์์โ๋ฅผ ๋๋ฌ UI๊ฐ ๋ณ๊ฒฝ๋์์ง๋ง, ์ค์ ์๋ฒ ์์ฒญ์ด ์คํจํ ์ํ์์ ์คํ๋ทฐ๋ฅผ ๋ซ์๋ค๊ฐ ๋ค์ ์ด๋ฉด โ์ข์์โ๊ฐ ๋ฐ์๋์ง ์์ ์ฌ์ฉ์๊ฐ ์ค๋ฅ๋ก ์ธ์ํ๋ ์ํฉ์ด ๋ฐ์ํ์ต๋๋ค.
์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ์๋ฒ ์ํ์ ํด๋ผ์ด์ธํธ ์ํ๋ฅผ ๋ถ๋ฆฌํ๊ธฐ๋ก ๊ฒฐ์ ํ์ต๋๋ค. ์๋ฒ๋ฅผ ํตํด์ ๋ฐ์์ค๋ ๋ฐ์ดํฐ๋ @tanstack/react-query
์์๋ง ๊ด๋ฆฌํ๊ณ , ํด๋ผ์ด์ธํธ์์๋ง ์ฌ์ฉํ๋ ๋ฐ์ดํฐ๋ Jotai๋ก ๊ด๋ฆฌํ์๋ ๊ฒฐ๋ก ์ ๋ด๋ ธ์ต๋๋ค. ์ด๋ฅผ ํตํด ์ฝ๋ ์ ์ง๋ณด์ ์ ๋ณต์ก์ฑ์ ์ค์ด๊ณ , ๋ฐ์ดํฐ๋ฅผ ์ผ๊ด์ ์ผ๋ก ๊ด๋ฆฌํ๋ฉฐ, ๋ฐ์ดํฐ ์ ํฉ์ฑ ๋ถ์ผ์น ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์์ ๊ฒ์ผ๋ก ๊ธฐ๋ํ์ต๋๋ค.
๊ธฐ์กด์ Jotai๋ก ๊ด๋ฆฌํ๋ ์๋ฒ ์ํ๋ฅผ @tanstack/react-query
๋ก ์์ ํ๋ ๊ณผ์ ์์ @tanstack/react-query
์ ๋๊ด์ ์
๋ฐ์ดํธ(Optimisic Update)์ ๋ํด ์๊ฒ๋์๊ณ , ์ด๋ฅผ ์๋น์ค์ ์ ์ฉํ๊ฒ ๋์์ต๋๋ค.
๋๊ด์ ์ ๋ฐ์ดํธ?
๋๊ด์ ์ ๋ฐ์ดํธ(Optimistic Update)๋ ์๋ฒ API ์๋ต์ ๋ฐ๊ธฐ ์ ์ UI๋ฅผ ๋จผ์ ๋ณ๊ฒฝํ๋ ๋ฐฉ์์ ๋๋ค. ์๋ฒ๋ก๋ถํฐ ๊ฒฐ๊ตญ ์ฑ๊ณต ์๋ต์ ๋ฐ์ ๊ฒ์ด๋ผ๊ณ ๋๊ด์ ์ผ๋ก ๊ฐ์ ํ๋ ๊ฒ์ ๋๋ค. ์ด๋ฅผ ํตํด ์ฌ์ฉ์์๊ฒ ๋ ๋น ๋ฅด๊ณ ๋ฐ์์ฑ ๋์ ๊ฒฝํ์ ์ ๊ณตํ ์ ์์ต๋๋ค.
ํ์ง๋ง ๋๊ด์ ์ ๋ฐ์ดํธ๋ฅผ ๋ฌด์กฐ๊ฑด ์ ์ฉํ๋ ๊ฒ์ด ์ข์๊น์?
ํฌ์คํธ ์์ฑ/์ญ์ /์ข์์, ๋๊ธ ์์ฑ/์ญ์ /์ ๊ณ /์ข์์ ๋ฑ @tanstack/react-query
๋ฅผ ์ ์ฉํด์ผ ํ ์๋ฒ ์ํ๋ ๋งค์ฐ ๋ง์์ต๋๋ค.
์ด ๋ชจ๋ ๋ถ๋ถ์ ๋๊ด์ ์ ๋ฐ์ดํธ๋ฅผ ์ ์ฉํ๋ ๊ฒ์ด ์ข์์ง ์๋ฌธ์ด ๋ค์์ต๋๋ค. ์๋ฅผ ๋ค์ด, ๋๊ธ ์์ฑ input์ ๊ธ์น์ด๋ฅผ ์ ๋ ฅํ๋ฉด API ์์ฒญ ์ ์๋ฌ๊ฐ ๋ฐํ๋ฉ๋๋ค. ๊ธ์น์ด ์๋ฌ์ผ ๊ฒฝ์ฐ, ํ ์คํธ๊ฐ input์ ๊ทธ๋๋ก ๋จ์์๊ณ ํ ์คํธ ๋ฉ์์ง๊ฐ ๋น๋๋ค. ๋ง์ฝ ๋๊ธ ์์ฑ์ ๋๊ด์ ์ ๋ฐ์ดํธ๋ฅผ ์ ์ฉํ๋ฉด, ๋๊ธ์ด ์ด๋ฏธ ์์ฑ๋ ๊ฒ์ฒ๋ผ ๋ณด์ฌ ์ฌ์ฉ์์๊ฒ ํผ๋์ ์ค ์ ์์ต๋๋ค. ๊ฒฐ๊ตญ ๊ธฐ๋ฅ๋ง๋ค ๋ค๋ฅด๊ฒ ํ๋จํ์ฌ ์ํฉ์ ๋ฐ๋ผ ์ ์ ํ๊ฒ ์ ์ฉํ๋ ๊ฒ์ด ์ค์ํ๋ค๋ ๊ฒ์ ๊นจ๋ฌ์์ต๋๋ค.
๋๊ด์ ์ ๋ฐ์ดํธ ๋ฐฉ์
์ ํฌ ํ์ ํฌ์คํธ, ๋๊ธ, ๋ต๊ธ ๋ฑ ์ข์์/์ข์์ ์ทจ์ ๊ธฐ๋ฅ์ ๋๊ด์ ์ ๋ฐ์ดํธ๋ฅผ ์ ์ฉํ๊ธฐ๋ก ๊ฒฐ์ ํ์ต๋๋ค.
์ ํฌ๊ฐ ๊ตฌํํ ๋ฏธ๋์ด ํฌ์คํธ ์ข์์ ๊ธฐ๋ฅ์ ๋๊ด์ ์ ๋ฐ์ดํธ ๋ฐฉ์์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
mutationFn
์ ์ํ๊ธฐ- ์ข์์, ์ข์์ ์ทจ์ ๊ธฐ๋ฅ์ ์ฌ๋ฌ๋ฒ ๋น ๋ฅด๊ฒ ํด๋ฆญ ์ ๋ค์์ API ์์ฒญ์ด ๊ฐ ์ ์์ผ๋ฏ๋ก ๋๋ฐ์ด์ค(debounce)๋ฅผ ์ ์ฉํ์ฌ API ์์ฒญ์ ์ฒ๋ฆฌํ์ต๋๋ค.
mutationFn: (isLike: boolean) => debouncedMutationFn({ isLike }),
- ์ข์์, ์ข์์ ์ทจ์ ๊ธฐ๋ฅ์ ์ฌ๋ฌ๋ฒ ๋น ๋ฅด๊ฒ ํด๋ฆญ ์ ๋ค์์ API ์์ฒญ์ด ๊ฐ ์ ์์ผ๋ฏ๋ก ๋๋ฐ์ด์ค(debounce)๋ฅผ ์ ์ฉํ์ฌ API ์์ฒญ์ ์ฒ๋ฆฌํ์ต๋๋ค.
onMutate
์ ์ํ๊ธฐ :onMutate
๋ mutation์ด ์ํ๋๊ธฐ ์ ์ ์คํ๋๋ ํจ์์ ๋๋ค.
- 1๏ธโฃ queryClient.cancelQueries ์ฒ๋ฆฌ: ๋๊ด์ ์
๋ฐ์ดํธ์ ๋ณ๊ฐ๋ก ๊ด๋ จ ๋ฐ์ดํฐ์ refetch๊ฐ ๋ฐ์ํ๋ฉด ๋ฐ์ดํฐ ๋์ฐฉ ํ์ด๋ฐ์ด ์๊ฐ๋ ค ์์๊ณผ ๋ค๋ฅธ ์ด์ ๋ฐ์ดํฐ๋ฅผ ๋ณด๊ฒ ๋ ์ ์์ต๋๋ค. ์ด๋ฅผ ๋ฐฉ์งํ๊ธฐ ์ํด
queryClient.cancelQueries
๋ฅผ ํธ์ถํฉ๋๋ค. ์๋ฅผ ๋ค์ด, ์ฌ์ฉ์๊ฐ โ์ข์์โ ๋ฒํผ์ ๋๋ฆ๊ณผ ๋์์ ํฌ์คํธ ๋ฐ์ดํฐ๊ฐ refetch๋๋ ์ํฉ์์ ๋๊ด์ ์ ๋ฐ์ดํธ๊ฐ ๋จผ์ ์ ์ฉ๋ ํ refetch๊ฐ ์ผ์ด๋๋ฉด ์ด์ UI ์ํ๊ฐ ๋ค์ ๋ณด์ด๋ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค. - 2๏ธโฃย ์ด์ ๋ฐ์ดํฐ return :
queryClient.getQueryData
๋ฅผ ํตํด ์ด์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์context
์ ์ ์ฅํ๊ณ ๋ฐํํฉ๋๋ค. - 3๏ธโฃย ๋๊ด์ ์
๋ฐ์ดํธ :
queryClient.setQueryData
๋ฅผ ํตํด ๋ณ๊ฒฝ๋ ๋ฐ์ดํฐ (nextData)๋ฅผ ๋ฏธ๋ฆฌ ์ ๋ฐ์ดํธ ํด์ค๋๋ค.onMutate: async (isLike: boolean) => { await queryClient.cancelQueries({ queryKey: getMediaPostKey }); // 1๏ธโฃ const previousData = queryClient.getQueryData<MediaPostVo['post']>(getMediaPostKey); // 2๏ธโฃ if (!previousData) return; const nextData = () => isLike ? likeById(previousData) : dislikeById(previousData); queryClient.setQueryData(getMediaPostKey, nextData); // 3๏ธโฃ return { previousData }; },
- 1๏ธโฃ queryClient.cancelQueries ์ฒ๋ฆฌ: ๋๊ด์ ์
๋ฐ์ดํธ์ ๋ณ๊ฐ๋ก ๊ด๋ จ ๋ฐ์ดํฐ์ refetch๊ฐ ๋ฐ์ํ๋ฉด ๋ฐ์ดํฐ ๋์ฐฉ ํ์ด๋ฐ์ด ์๊ฐ๋ ค ์์๊ณผ ๋ค๋ฅธ ์ด์ ๋ฐ์ดํฐ๋ฅผ ๋ณด๊ฒ ๋ ์ ์์ต๋๋ค. ์ด๋ฅผ ๋ฐฉ์งํ๊ธฐ ์ํด
onError
์ ์ํ๊ธฐ :onError
๋ mutation์ด ์คํจํ์ ๋ ํธ์ถ๋๋ ํจ์์ ๋๋ค.setQueryData
๋ฅผ ํตํดcontext
์ ์ ์ฅํด ๋ ์ด์ ๋ฐ์ดํฐ๋ฅผ ๋ค์ ์ธํ ํ์ฌ UI๋ฅผ ๋ณต๊ตฌํฉ๋๋ค.onError: (_err, _vars, context) => { if (context?.previousData) { queryClient.setQueryData(getMediaPostKey, { ...context.previousData }); } }
onSettled
์ ์ํ๊ธฐ :onSettled
๋ ์์ฒญ ์ฑ๊ณต ๋๋ ์คํจํ ํ ํญ์ ์คํ๋๋ ํจ์์ ๋๋ค.queryClient.invalidateQueries
๋ฅผ ํธ์ถํ์ฌ ์ต์ข ์ ์ผ๋ก ์๋ฒ ๋ฐ์ดํฐ๋ฅผ ๋๊ธฐํํฉ๋๋ค.onSettled: () => queryClient.invalidateQueries({ queryKey: getMediaPostKey }),
๊ณต์๋ฌธ์์ ๋์์๋
onSettled
์ ์๋ ์ด๋ฒ ์์ ์์ ์ ์ธํ์ต๋๋ค. ๊ทธ ์ด์ ๋ ๋ฌดํ์คํฌ๋กค๋ก ๊ตฌํ๋์ด ์๋ ๋ฆฌ์คํธ์์ ์ ํํ ํด๋น ํ์ด์ง์ querykey์ ํ์ํ id ๊ฐ์ ์์ง ๋ชปํ๊ธฐ ๋๋ฌธ์ ๋๋ค. ๋ํ, ๋๊ธ ์คํ๋ทฐ๋ฅผ ๋ค์ ์ด๊ฑฐ๋ ํด๋น ํฌ์คํธ ํญ์ ๋๋ ์ ๋ ์ต์ ํํ๋๋ก ์ค์ ํด๋์๊ธฐ ๋๋ฌธ์onSettled
์queryClient.invalidateQueris
๊ฐ ๋ถํ์ํ๋ค๊ณ ํ๋จํ์ต๋๋ค.
๋๊ด์ ์ ๋ฐ์ดํธ ์ ์ฉ ์ ํ๋ฉด
๋๊ด์ ์
๋ฐ์ดํธ ์ ์ฉ ๊ฒฐ๊ณผ ํ๋ฉด
โ
ย ๋๋ฐ์ด์ค ์ ์ฉ
โ
ย ๋๊ด์ ์
๋ฐ์ดํธ ์ ์ฉ
์๋ฌ ๋ฐ์ ์ ํ๋ฉด
์ถ๊ฐ์ ์ผ๋ก ๊ณ ๋ฏผํ ๋ถ๋ถ
invalidateQueries vs refetchQueries
๋๊ธ ์คํ๋ทฐ๊ฐ ์ด๋ฆด ๋๋ง๋ค ์ต์ ๋ฐ์ดํฐ๋ฅผ ๋ณด์ฌ์ฃผ๊ธฐ ์ํด ๊ณ ๋ฏผํ๋ ๋ค์ํ ๋ฐฉ๋ฒ์ ์๊ฐํ๋ ค ํฉ๋๋ค. @tanstack/react-query
์์ ์ฟผ๋ฆฌ ๋ฐ์ดํฐ๋ฅผ ๊ด๋ฆฌํ๋ ๋ ๊ฐ์ง ์ฃผ์ ๋ฐฉ๋ฒ์ refetchQueries
์ invalidateQueries
์
๋๋ค. ์ด ๋์ ์ฟผ๋ฆฌ ๋ฐ์ดํฐ๋ฅผ ๊ฐฑ์ ํ๋ ๋ฐฉ์์์ ์ค์ํ ์ฐจ์ด๋ฅผ ๋ณด์
๋๋ค.
refetchQueries
๋ ๊ฐ์ ๋ก ๋ฐ์ดํฐ๋ฅผ โ๋ค์ ๊ฐ์ ธ์ค๋โ ๋์์ ์ํํฉ๋๋ค. ์ฆ, ํธ์ถ๋๋ฉด ์บ์ ์ํ์ ์๊ด์์ด ๋ฌด์กฐ๊ฑด ๋ฐ์ดํฐ๋ฅผ ์๋ฒ๋ก๋ถํฐ ์๋ก ์์ฒญํฉ๋๋ค. ๋ฐ๋ผ์ refetch๋ ํน์ ์์ ์ ์ต์ ๋ฐ์ดํฐ๊ฐ ๋ฐ๋์ ํ์ํ ๊ฒฝ์ฐ์ ์ ์ฉํฉ๋๋ค.
๋ฐ๋ฉด, invalidateQueries
๋ ๋ฐ์ดํฐ๋ฅผ โ๋ฌดํจํํ๋โ ๋์์
๋๋ค. ํน์ ์ฟผ๋ฆฌ ๋ฐ์ดํฐ๋ฅผ โ์ค๋๋(stale) ์ํโ๋ก ํ์ํ๊ณ , ์ด ์ฟผ๋ฆฌ๋ฅผ ๊ด์ฐฐํ๋ ์ปดํฌ๋ํธ๊ฐ ๋ง์ดํธ๋ ๋ ์ต์ ๋ฐ์ดํฐ๋ฅผ ๋ค์ ๊ฐ์ ธ์ค๊ฒ ๋ฉ๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด ๋ถํ์ํ ๋คํธ์ํฌ ์์ฒญ์ ์ค์ด๊ณ , ์ฌ์ฉ์๊ฐ ์บ์๋ ๋ฐ์ดํฐ๋ฅผ ๋จผ์ ๋ณด๋ฉด์ ๋ ๋น ๋ฅธ ๋ฐ์์ฑ์ ๋๋ ์ ์๊ฒ ํด์ค๋๋ค.
๋๊ธ ์คํ๋ทฐ๋ ์ฌ์ฉ์ ๊ฒฝํ์ด ์ค์ํ ๊ธฐ๋ฅ์ด๋ฏ๋ก unmount ์ invalidateQueries
๋ฅผ ํธ์ถํ๋ ๋ฐฉ์์ ์ ํํ์์ต๋๋ค. ์ด ๋ฐฉ์์ ํตํด ์ฌ์ฉ์๋ ์คํ๋ทฐ๋ฅผ ๋ค์ ์ด์์ ๋ ์บ์๋ ๊ธฐ์กด ๋ฐ์ดํฐ๊ฐ ์ฆ์ ํ๋ฉด์ ํ์๋์ด ๋ก๋ฉ ์๊ฐ์ ์ค์ผ ์ ์์๊ณ , ๊ทธ ์ฌ์ด ๋ฐฑ๊ทธ๋ผ์ด๋์์ ์ต์ ๋ฐ์ดํฐ๊ฐ ์
๋ฐ์ดํธ๋์ด ์์ฐ์ค๋ฝ๊ฒ ํ๋ฉด์ด ๊ฐฑ์ ๋๋ ๋งค๋๋ฌ์ด ๊ฒฝํ์ ์ ๊ณตํ ์ ์์์ต๋๋ค. ์ด์ฒ๋ผ ์ต์ ํ ๋ฐฉ์์ ํ๋ก์ ํธ์ ํน์ฑ๊ณผ ์๊ตฌ์ฌํญ์ ๋ฐ๋ผ ์ ์ ํ๊ฒ ์ค์ ํ๋ ๊ฒ์ด ์ข์ต๋๋ค.
์ฟผ๋ฆฌํค ๊ด๋ฆฌ ๋ฐฉ๋ฒ
Jotai์์ @tanstack/react-query
๋ก ์ ํํ๋ฉฐ ์ฟผ๋ฆฌ ํค ๊ด๋ฆฌ ๋ฐฉ์๋ ๋ณ๊ฒฝ๋์ด ์ ํฌ์ ๋ฐฉ์์ ๊ณต์ ํฉ๋๋ค.
๊ธฐ์กด์๋ ์ฌ์ฉํ๋ ๊ณณ๋ง๋ค ํค๋ฅผ ์ผ์ผ์ด ์ ์ด์ฃผ๋ ๋ฐฉ์์ด์๋ค๋ฉด, ๋ณ๊ฒฝ๋ ๋ฐฉ์์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
export const QueryKeys = {
// ๋๊ธ
comment: {
rootKey: ['getComment'],
detailKey: ({ tab, commentId }: { tab: TabT; commentId?: number }) => ['getComment', { tab, commentId }]
},
...
// ๋ฏธ๋์ด
mediaPost: {
rootKey: ['getMediaPost'],
detailKey: ({ postId }: { postId: number }) => ['getMediaPost', { postId }]
},
...
}
ํ๋์ QueryKeys ๋ผ๋ Constant ๊ฐ์ฒด๋ฅผ ๋ง๋ค์ด ๊ทธ ๋ด๋ถ์ ๊ฐ ํค์ ๋ง๋ ์ด๋ฆ(ex. comment)์ ์ค์ ํ์ฌ ๋ด๋ถ์ rootKey
, detailKey
๋ก ๋๋์ด ๊ด๋ฆฌํ์ต๋๋ค. ํ๊ณณ์ ๋ชจ์์ ์ฟผ๋ฆฌ ํค๋ฅผ ๊ด๋ฆฌํ๋ค ๋ณด๋ ์ ์ง๋ณด์์ฑ์ด ์ข์์ก๊ณ , ์ฟผ๋ฆฌ ํค๋ฅผ ์๋ชป ์
๋ ฅํ๋ ์ค์๋ ๋ฐฉ์งํ ์ ์์์ต๋๋ค.
// ์ฌ์ฉํ๋ ๊ณณ ์์
const getMediaPostKey = QueryKeys.mediaPost.detailKey({ postId });
๋ง๋ฌด๋ฆฌํ๋ฉฐ
์ด๋ฒ ํฌ์คํธ์์๋ fromm ์ฑ๋ ์๋น์ค์ ์๋ฒ๋ฐ์ดํฐ๋ฅผ @tanstack/react-query
๋ก ๊ด๋ฆฌํ๊ฒ ๋ ๋ฐฐ๊ฒฝ๋ถํฐ ๋๊ด์ ์
๋ฐ์ดํธ, ์ฟผ๋ฆฌ ํค ๊ด๋ฆฌ ๋ฐฉ์๊น์ง ๊ณต์ ๋๋ ธ์ต๋๋ค.
Jotai๋ก ๊ด๋ฆฌํ๋ ์ด๊ธฐ ๋ฌธ์ ๋ถํฐ ์ต์ ์ ์ฟผ๋ฆฌ ํค๋ฅผ ์ฐพ์ ์ ์ฉํ๊ธฐ๊น์ง ์๋ง์ ๊ณ ๋ฏผ๊ณผ ์ํ์ฐฉ์ค๊ฐ ์์์ต๋๋ค. ๊ทธ ๊ฒฐ๊ณผ, ๋ฐ์ดํฐ ์ ํฉ์ฑ ์ด์๋ฅผ ํด๊ฒฐํ๊ณ , โ์ข์์โ์ ๊ฐ์ ํต์ฌ ๊ธฐ๋ฅ์ ๋ํ ์ฌ์ฉ์์ ๋ฐ์ ์๋๊ฐ ์ฒด๊ฐ๋ ๋งํผ ๋นจ๋ผ์ก์ต๋๋ค. ์ด ๋ชจ๋ ๊ณผ์ ์ด ๋ ๋์ ์๋น์ค๋ฅผ ํฅํ ์ ํฌ ํ์ ๋์์๋ ๋ ธ๋ ฅ์ด์๋ค๊ณ ์๊ฐํฉ๋๋ค.
์์ผ๋ก๋ ๋ ธ๋จธ์ค ํ๋ก ํธ์๋ ํ์ ๋จ์ํ ์๋ก์ด ๊ธฐ๋ฅ ๊ฐ๋ฐ ๋ฟ๋ง ์๋๋ผ, ์ฌ์ฉ์ ๊ฒฝํ ๊ฐ์ ๊ณผ ๋ฐ์ดํฐ ์์ ์ฑ์ ์ํด ์ง์์ ์ผ๋ก ๋ ธ๋ ฅํ ๊ฒ์ ๋๋ค. ๊พธ์คํ ๋ฐ์ ํด๋๊ฐ๋ fromm ์ฑ๋ ์๋น์ค ๋ง์ ๊ด์ฌ๊ณผ ๊ธฐ๋ ๋ถํ๋๋ฆฝ๋๋ค!
๊ฐ์ฌํฉ๋๋ค ๐
ํ์ฌ ํ๋ก ํธ์๋ ํ์ ํจ๊ป ์๋น์ค์ ํ์ง์ ๋์ด๊ธฐ ์ํด ๊ณ ๋ฏผํ๊ณ ํจ๊ป ์ฑ์ฅํด๋๊ฐ ๊ฐ๋ฐ์๋ฅผ ์ฐพ๊ณ ์์ต๋๋ค!
๊ด์ฌ ์์ผ์ ๋ถ๋ค์ ์๋์ ์๋ ์ฑ์ฉํ์ด์ง๋ฅผ ํตํด ์ธ์ ๋ ์ง ์ง์ ๋ถํ๋๋ฆฝ๋๋ค. ๐ค