let's get IT with DAVINA ๐ป
React Query ๋ณธ๋ฌธ
โ๏ธ ์ฌ์ Knowledge ++
FE ์ํ ๊ด๋ฆฌ
- redux, mobx, recoil ๋ฑ ๋ค์ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์กด์ฌ
์ํ๋?
์ฃผ์ด์ง ์๊ฐ์ ๋ํด ์์คํ ์ ๋ํ๋ด๋ ๊ฒ์ผ๋ก ์ธ์ ๋ ์ง ๋ณ๊ฒฝ๋ ์ ์์.
์ฆ, ๋ฌธ์์ด, ๋ฐฐ์ด, ๊ฐ์ฒด ๋ฑ์ ํํ๋ก ์์ฉ ํ๋ก๊ทธ๋จ์ ์ ์ฅ๋ ๋ฐ์ดํฐ → ๊ฐ๋ฐ์ ์ ์ฅ์์๋ ๊ด๋ฆฌํด์ผํ๋ ๋ฐ์ดํฐ๋ค
์ํ๊ด๋ฆฌ?
์๊ฐ์ ํ๋ฆ์ ๋ฐ๋ผ ๋ณํํ๋ ์ํ๋ฅผ ๊ด๋ฆฌํ๋ ๊ฒ
React์์ ๋จ๋ฐฉํฅ ๋ฐ์ธ๋ฉ์ด๋ฏ๋ก props drilling ์ด์๋ ์กด์ฌ (redux, mobx์ ๊ฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํด์ ํด๊ฒฐํ๊ธฐ๋ ํจ)
- store์ ์ ์ญ์ํ๊ฐ ์ ์ฅ๋๊ณ ๊ด๋ฆฌ๋๋ ๊ณต๊ฐ์ธ๋ฐ redux, redux-saga๋ฐฉ์์ผ๋ก ๋น๋๊ธฐ ์์ฒญ์ ๊ตฌํํ๊ฒ ๋๋ฉด redux ๊ตฌํํ๋ ๋ชจ๋์ APIํต์ ๊ด๋ จ ์ฝ๋๊ฐ ๋๋ถ๋ถ์ด๊ฒ ๋จ
- ๋น์ทํ ๊ตฌ์กฐ์ API ํต์ ์ฝ๋ ๋ฐ๋ณต (loading, error, fetching ๋ฑ)
์๋ฒ์์ ๋ฐ์์ผ ํ๋ ์ํ๋ค์ ํน์ฑ
- client์์ ์ ์ดํ๊ฑฐ๋ ์์ ๋์ง ์์ ์๊ฒฉ์ ๊ณต๊ฐ์์ ๊ด๋ฆฌ๋๊ณ ์ ์ง๋จ
- fetching์ด๋ updating์ ๋น๋๊ธฐ API๊ฐ ํ์ํจ
- ๋ค๋ฅธ ์ฌ๋๋ค๊ณผ ๊ณต์ ๋๋ ๊ฒ์ผ๋ก ์ฌ์ฉ์๊ฐ ๋ชจ๋ฅด๋ ์ฌ์ด์ ๋ณ๊ฒฝ๋ ์ ์์
- ์ ๊ฒฝ์ฐ์ง ์๋๋ค๋ฉด ์ ์ฌ์ ์ผ๋ก "out of dated"๊ฐ ๋ ์ ์์..
- ์ฌ์ค์ FE์์ ์ด ๊ฐ๋ค์ด ์ ์ฅ๋์ด์๋ state๋ค์ ์ผ์ข ์ ์บ์
Client State vs Server State
- ์ํ๋ฅผ ํฌ๊ฒ Client State ์ Server State๋ก ๊ตฌ๋ถ ๊ฐ๋ฅ
- key point๋ Ownership์ด ์๋ ๊ณณ
Client State | Server State |
Client์์ ์์ ํ๋ฉฐ ์จ์ ํ ์ ์ด ๊ฐ๋ฅ | Client์์ ์ ์ดํ๊ฑฐ๋ ์์ ๋์ง ์๋ ์๊ฒฉ์ ๊ณต๊ฐ์์ ๊ด๋ฆฌ๋๊ณ ์ ์ง ๋จ |
์ด๊ธฐ๊ฐ ์ค์ ์ด๋ ์กฐ์์ ์ ์ฝ์ฌํญ ์์ | Fetching / Updating์ ํ์ํ ๋น๋๊ธฐ API๊ฐ ํ์ํจ |
๋ค๋ฅธ ์ฌ๋๋ค๊ณผ ๊ณต์ ๋์ง ์์ผ๋ฉฐ Client ๋ด์์ UI/UX ํ๋ฆ์ด๋ ์ฌ์ฉ์ ์ธํฐ๋ ์ ์ ๋ฐ๋ผ ๋ณํ ์ ์์ | ๋ค๋ฅธ ์ฌ๋๋ค๊ณผ ๊ณต์ ๋๋ ๊ฒ์ผ๋ก ์ฌ์ฉ์๊ฐ ๋ชจ๋ฅด๋ ์ฌ์ด์ ๋ณ๊ฒฝ๋ ์ ์์ |
ํญ์ Client ๋ด์์ ์ต์ ์ํ๋ก ๊ด๋ฆฌ๋จ | ์ ๊ฒฝ ์ฐ์ง ์๋๋ค๋ฉด ์ ์ฌ์ ์ผ๋ก "out of date"๊ฐ ๋ ๊ฐ๋ฅ์ฑ์ ์ง๋ |
React Query ์ค์น
$ npm i @tanstack/react-query
# or
$ yarn add @tanstack/react-query
import {
useQuery,
useMutation,
useQueryClient,
QueryClient,
QueryClientProvider,
} from '@tanstack/react-query'
React Query ์ ์
- ์๋ฒ ์ํ๋ฅผ ๊ด๋ฆฌํ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ, ์บ์, ๋๊ธฐํ, ๋ฐ์ดํฐ ์ ๋ฐ์ดํธ ๋ฑ์ ๊ธฐ๋ฅ์ด ์๋ค.
- ๊ธฐ์กด์ client state๋ฅผ ๋ค๋ฃจ๋ ์ํ๊ด๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค๊ณผ ๋ค๋ฅด๊ฒ sever state๋ฅผ Fetching, Caching, ๋น๋๊ธฐ์ ์ผ๋ก ์ ๋ฐ์ดํธ ํ๋๋ฐ ๋์์ ์ฃผ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค.
- ๊ณต์ ๋ฌธ์ ์์ โฝ
- React์์ ์ฐ๋ ค๋ฉด QueryClientProvider ํ์!
import {
QueryClient,
QueryClientProvider,
useQuery,
} from "@tanstack/react-query";
const queryClient = new QueryClient();
export default function App() {
return (
<QueryClientProvider client={queryClient}>
<Example />
</QueryClientProvider>
);
}
function Example() {
const { isLoading, error, data } = useQuery({
queryKey: ["repoData"],
queryFn: () =>
fetch(
"https://api.github.com/repos/tannerlinsley/react-query"
).then((res) => res.json()),
});
if (isLoding) return "Loading...";
if (error) return "An error has occurred: " + error.message;
return (
<div>
<h1>{data.name}</h1>
<p>{data.discription}</p>
<strong>๐ {data.subscribers_count} </strong>
<strong>โจ {data.stargazers_count}</strong>{" "}
<strong>๐ด {data.forks_count}</strong>
</div>
);
}
โ 3 core concepts of React Query :
1๏ธโฃ Queries
- Queries๋ ๋ฐ์ดํฐ fetching์ฉ (GET ๋ฉ์๋)
- useQuery
- ์๋ฒ๋ก๋ถํฐ ๋ฐ์ดํฐ๋ฅผ ์กฐํํ ๋ ์ฌ์ฉํ๋ค.
- ์ฒซ๋ฒ์งธ ์ธ์๊ฐ์ธ queryKey๋ฅผ ์ด์ฉํ์ฌ ์บ์ฑ๋ ๊ฐ์ ์ด์ฉํ๊ฑฐ๋ API๋ก ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์จ๋ค.
- Query Key && Query Function ํ์ (key & value ๋งคํ ๊ตฌ์กฐ)
- Query Key๋ string type/array type ๋ ๊ฐ์ง๋ก ๊ด๋ฆฌ ๊ฐ๋ฅ
- Query Function์ Promise๋ฅผ ๋ฐํํ๋ ํจ์
- useQuery()์ ๋ฐํ ๊ฐ
โ data : ๋ง์ง๋ง์ผ๋ก ์ฑ๊ณตํ resolved๋ ๋ฐ์ดํฐ (Response)
โ error : ์๋ฌ๊ฐ ๋ฐ์ํ์ ๋ ๋ฐํ ๋๋ ๊ฐ์ฒด
โ isFetching : Request๊ฐ in-flight ์ค์ผ ๋ true
โ status, isLoading, isSuccess, isLoading ๋ฑ๋ฑ --> ํ์ฌ query์ ์ํ
โ refetch : ํด๋น query refetch ํ๋ ํจ์ ์ ๊ณต
โ remove : ํด๋น query cache์์ ์ง์ฐ๋ ํจ์ ์ ๊ณต
- 3๋ฒ์งธ ์ธ์๋ก option ๋ฃ๊ธฐ ๊ฐ๋ฅ
โ onSuccess, onError, onSettled : query fetching ์ฑ๊ณต/ ์คํจ/ ์๋ฃ ์ ์คํํ Side Effect ์ ์
โ enabled : ์๋์ผ๋ก query๋ฅผ ์คํ์ํฌ์ง ๋ง์ง ์ฌ๋ถ
โ retry : query ๋์ ์คํจ ์, ์๋์ผ๋ก retry ํ ์ง ๊ฒฐ์ ํ๋ ์ต์
โ select : ์ฑ๊ณต ์ ๊ฐ์ ธ์จ data๋ฅผ ๊ฐ๊ณตํด์ ์ ๋ฌ
โ keepPreviousData : ์๋ก๊ฒ fectching ์ ์ด์ ๋ฐ์ดํฐ ์ ์ง ์ฌ๋ถ
โ refetchInterval : ์ฃผ๊ธฐ์ ์ผ๋ก refetch ํ ์ง ๊ฒฐ์ ํ๋ ์ต์
2๏ธโฃ Mutations
- get ์์ฒญ์ด์ธ์ ์๋ฒ ์ํ๋ฅผ update ํ ๋ ์ฌ์ฉ( POST, DELETE, PATCH)
- useMutation()์ ๊ฒฝ์ฐ Query key ์์ด ํ๋ก๋ฏธ์ค ๋ฐํ ํจ์๋ง ์ธ์๋ก ์ ๋ฌํด ์ฃผ๋ฉด ๋จ
- ๋จ, Query key ๋ฃ์ด์ฃผ๋ฉด dev tools์์ ๋ณผ ์ ์์
- ๋ฐํ ๊ฐ
โ mutate : mutation์ ์คํํ๋ ํจ์
โ mutateAsync : mutate์ ๋น์ทํ๋ Promise๋ฅผ ๋ฐํํจ
โ reset : mutation ๋ด๋ถ ์ํ clean
โ ๋๋จธ์ง๋ useQuery์ ์ ์ฌ ํฉ๋๋ค.
- ์ต์ ๊ฐ
โ onMutate : ๋ณธ๊ฒฉ์ ์ธ Mutation ๋์ ์ ์ ๋จผ์ ๋์ํ๋ ํจ์, Optimistic update ์ ์ฉํ ๋ ์ ์ฉ
โ ๋๋จธ์ง๋ useQuery์ ์ ์ฌ
Optimistic update ๋?
๋๊ด์ ์ ๋ฐ์ดํธ
์ฆ, API ์์ฒญ์ด ์ฑ๊ณตํ ๊ฒ์ด๋ผ ๋ณด๊ณ UI๋ฅผ ๋จผ์ ์ ๋ฐ์ดํธ, ์ฑ๊ณต ์ ๊ทธ๋๋ก ๊ฐ๊ณ ์คํจ ์ ๋กค๋ฐฑ
3๏ธโฃ Query Invalidation
- ๊ฐ๋จํ queryClient๋ฅผ ํตํด invalidate ๋ฉ์๋๋ฅผ ํธ์ถํ๋ฉด ๋
// Invalidate every query in the cache
queryClient.invalidateQueryies()
// Invalidate every query with a key that starts with 'todos'
queryClient.invalidateQueryies('todos')
- ํด๋น key๋ฅผ ๊ฐ์ง query๋ stale ์ทจ๊ธ ๋๊ณ , ํ์ฌ rendering ๋๊ณ ์๋ qeury๋ค์ ๋ฐฑ๊ทธ๋ผ์ด๋์์ refetch ๋ฉ๋๋ค.
Caching & Synchronization
Query ์ต์ ์ผ๋ก cacheTime, staleTime, refetchOnWindowFocus, refetchOnMount ๋ฑ์ด ์๋ค
React-query์์ Cache
โ cacheTime : ๋ฉ๋ชจ๋ฆฌ์ ์ผ๋ง๋งํผ ์์ ๊ฑด์ง(ํด๋น ์๊ฐ ์ดํ GC์ ์ํด ์ฒ๋ฆฌ, default 5๋ถ)
โ staleTime : ์ผ๋ง์ ์๊ฐ์ด ํ๋ฅธ ํ์ ๋ฐ์ดํฐ๋ฅผ stale ์ทจ๊ธ ํ ๊ฒ์ธ์ง(default 0)
โ refetchOnMount / refetchOnWindowFocus / refetchOnReconnect : true ์ด๋ฉด Mount / window focus / reconnect ์์ ์ data๊ฐ stale์ด๋ผ๊ณ ํ๋จ๋๋ฉด ๋ชจ๋ refetch (๋ชจ๋ default true)
๋ฆฌ์กํธ ์ฟผ๋ฆฌ ์ํ ํ๋ฆ
- staleTime์ default ๊ฐ์ด 0์ด๋ฏ๋ก customํ์ง ์๋๋ค๋ฉด fetching ๋ ๋ ๋ฐ๋ก stale์ํ๋ก ๋์ด๊ฐ
- staleTime์ customํด์ 0๋ณด๋ค ํฌ๊ฒ ๋ง๋ค์ด ์ฃผ๋ฉด fresh ์ํ๋ฅผ ์ ์ง
- stale ์ํ๋ ์คํฌ๋ฆฐ์์ ์ฌ์ฉ๋๋ ๋์ active ์ํ๋ก ์ ์ง ๋จ
- ์คํฌ๋ฆฐ์์ ์ฌ์ฉํ์ง ์๋๋ค๋ฉด inactive ์ํ๋ก ๋ฐ๋๊ณ ,cacheTime์ด ๋ง๋ฃ๋๊ธฐ ์ ๊น์ง ๋ฉ๋ชจ๋ฆฌ์์ ์ ์ง๋จ
- cacheTime์ด ๋ง๋ฃ๋๋ฉด GC์ ์ํด ์ฒ๋ฆฌ๋จ
- ์ฆ, ์ํ๊ฐ fresh ํ๋ค๋ฉด refetch๊ฐ ์ผ์ด๋์ง ์์!
์ ๋ฆฌ
โ fresh : ์๋กญ๊ฒ ์ถ๊ฐ๋ ์ฟผ๋ฆฌ & ๋ง๋ฃ๋์ง ์์ ์ฟผ๋ฆฌ โ ์ปดํฌ๋ํธ๊ฐ ๋ง์ดํธ, ์ ๋ฐ์ดํธ๋์ด๋ ๋ฐ์ดํฐ ์ฌ์์ฒญ โ
โ fetching : ์์ฒญ ์ค์ธ ์ฟผ๋ฆฌ
โ stale : ๋ง๋ฃ๋ ์ฟผ๋ฆฌ โ ์ปดํฌ๋ํธ๊ฐ ๋ง์ดํธ, ์ ๋ฐ์ดํธ๋๋ฉด ๋ฐ์ดํฐ ์ฌ์์ฒญ โญ๏ธ
โ inactive : ๋นํ์ฑํ๋ ์ฟผ๋ฆฌ โ ํน์ ์๊ฐ์ด ์ง๋๋ฉด ๊ฐ๋น์ง ์ปฌ๋ ํฐ์ ์ํด ์ ๊ฑฐ
zero-config (๊ธฐ๋ณธ ์ค์ default ๊ฐ)
- Queries์์ cached data๋ ์ธ์ ๋ stale ์ทจ๊ธ
- ๊ฐ ์์ ์์ data๊ฐ stale์ด๋ผ๋ฉด ํญ์ refetch ๋ฐ์
- inactive Query๋ค์ 5๋ถ ๋ค GC์ ์ํด ์ฒ๋ฆฌ
- Query ์คํจ ์ 3๋ฒ๊น์ง retry ๋ฐ์
React-query์์ ๋ฐ์ดํฐ ๊ด๋ฆฌ
- ๋ง์น ์ ์ญ์ํ์ฒ๋ผ ๊ด๋ฆฌ๋๋ ๋ฐ์ดํฐ → ContextAPI ์ฌ์ฉ
- QueryClient ๋ด๋ถ์ ์ผ๋ก Context ์ฌ์ฉ
์ฐธ์กฐ
https://hoime.tistory.com/92?category=534509
https://manon-kim.tistory.com/entry/React-Query
'DEV_IN > React' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
React๋ก TodoApp ๋ง๋ค๊ธฐ (3)Delete,Update ๊ธฐ๋ฅ ๊ฐ๋ฐ (2) | 2023.03.02 |
---|---|
React๋ก TodoApp ๋ง๋ค๊ธฐ (2)Create ๊ธฐ๋ฅ ๊ฐ๋ฐ (2) | 2023.03.02 |
React๋ก TodoApp ๋ง๋ค๊ธฐ (1)Setup (4) | 2023.03.02 |
JSX (2) | 2023.02.21 |
What is React? (3) | 2023.02.21 |
Comments