
UI/UX์ ์ค์์ฑ๊ณผ ํจ๊ป ํ๋ก๋ํธ ๊ท๋ชจ๊ฐ ์ปค์ง๋ฉด์ ํ๋ก ํธ์๋์์ ๊ด๋ฆฌํด์ผํ๋ ์ํ๊ฐ ๋ง์์ก๋ค.
๊ธฐ์กด์๋ ์๋ฒ์ํ์ ํด๋ผ์ด์ธํธ์ํ๋ฅผ ๊ตฌ๋ถํ์ง์๊ณ ์ ์ญ์ํ๊ด๋ฆฌ ๋๊ตฌ๋ฅผ ํตํด ๊ด๋ฆฌํ๋ค.
์ด๋ฌ๋ค๋ณด๋ ์ ์ญ์ํ๊ฐ ์ ์ฅ๋์ด์ผํ store์ ์ํ๊ด๋ฆฌ๋ณด๋จ APIํต์ ์ ์ํ ์ฝ๋๋ก ๋๋ฐฐ๋์๋ค.
์ด๋ฅผ ํด๊ฒฐํ๊ธฐ์ํด ์๋ฒ์ํ๊ด๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ๋ฑ์ฅํ๋ค.
๋๋ถ๋ถ์ ๊ธฐ์กด ์ํ ๊ด๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ํด๋ผ์ด์ธํธ ์ํ ์์ ์๋ ์ ํฉํ์ง๋ง ๋น๋๊ธฐ ๋๋ ์๋ฒ ์ํ ์์ ์๋ ์ ํฉํ์ง ์์ต๋๋ค.
TanStack-Query Docs Overview
์ ์ญ์ํ๊ด๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ(Redux, MobX...) + ๋ฏธ๋ค์จ์ด(React-Saga, React-Thunk...)๋ฅผ ์ด์ฉํด ์๋ฒ์ํ์ ํด๋ผ์ด์ธํธ์ํ๋ฅผ ํ๋ฒ์ ํธ๋ค๋ง โก๏ธ ๋ณต์ก๋ ์์น(๋ณด์ผ๋ฌ ํ๋ ์ดํธ๋ ์๋นํจ), ์ฝ๋๋ ์ฆ๊ฐ
์๋ฒ์ํ๊ด๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ(React-query, SWR...) ๋ฑ์ฅ์ผ๋ก ์๋ฒ์ํ์ ํด๋ผ์ด์ธํธ ์ํ๋ฅผ ๋ถ๋ฆฌํ์ฌ ๊ด๋ฆฌ โก๏ธ ๋ณต์ก๋ ๊ฐ์, ์ฝ๋๋ ๊ฐ์
๋ฆฌ๋์ค๋ ์์ํจ์๋ฅผ ์งํฅํด์ ๋น๋๊ธฐ์ฒ๋ฆฌ์๋ ๋ถ์ ํฉํ๊ธฐ ๋๋ฌธ์ ๋ฏธ๋ค์จ์ด๋ก ์ด๋ฅผ ํด๊ฒฐํ๋ค.
์ด๋ฅผ ํตํด ๋น๋๊ธฐ์ ์ธ ์๋ฒ์ํ๊ด๋ฆฌ๋ฅผ ์ํํ ์ ์์ง๋ง ์๋ฒ์ํ๋ง์ ์ํ ๋ก์ง์ด ๋น๋ํด์ง๋ค.
๋ฆฌ๋์ค ์์ฒด๊ฐ ์๋นํ ์์ ๋ณด์ผ๋ฌ ํ๋ ์ดํธ๋ฅผ ์๊ตฌํ๊ธฐ ๋๋ฌธ์ ์ฝ๋๋์ด ์ฆ๊ฐํ๋ค.
๊ทธ๋ฆฌ๊ณ ์ด๋ฅผ ๊ฐ๊ฐ์ API ๋ง๋ค ๋ฐ๋ณตํด์ผํ๋ค.
๐ ๊ทธ๋ฆผ์ถ์ฒ
๊ทธ๋ ๋ค๋ฉด ์๋ฒ ์ํ์ ํด๋ผ์ด์ธํธ ์ํ๊ฐ ๋ญ๊น? ๋ญ ๋๋ฌธ์ ์ด ๋์ ์ด์ํํด์ ๊ด๋ฆฌํด์ผ๋ ๊น?
์๋ฒ์ํ๋ ํด๋ผ์ด์ธํธ์ํ์ ๋ค๋ฅด๊ฒ ๋์ ์ด๋ฏ๋ก ์๊ฐ์ ๋ฐ๋ฅธ ๋ฐ์ดํฐ์ ๋ณํ๋ฅผ ํธ๋ํน ํด์ผํ๊ณ ์ฑ๋ฅ์ต์ ํ๋ฅผ ์ํด ์์ฒญ์ ์ต๋ํ ์ค์ฌ์ผํ๋ค.
์ฆ, ์ฑ๊ฒฉ์ด ๋ค๋ฅธ ํด๋ผ์ด์ธํธ ์ํ ๊ด๋ฆฌ์ ์๋ฒ ์ํ ๊ด๋ฆฌ๋ฅผ ๋ถ๋ฆฌํจ์ผ๋ก์จ ์บ์ฑ๋ฅผ ํตํ ์ฑ๋ฅํฅ์, ๊ด๋ฆฌ ๋ฐ ์ ์ง๋ณด์๋ฅผ ์ฉ์ดํ๊ฒํ ์ ์๋ค.
| ๊ตฌ๋ถ | ์๋ฒ ์ํ | ํด๋ผ์ด์ธํธ ์ํ |
|---|---|---|
| ์ ์ฅ ์์น | ์น์๋ฒ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค | ์ฌ์ฉ์์ ๋ธ๋ผ์ฐ์ ๋ ์ ํ๋ฆฌ์ผ์ด์ |
| ํน์ง | ์ค์์ง์ค์, ๋์ , ์ฌ๋ฌ ์ฌ์ฉ์ ๊ฐ ๊ณต์ | ๋ก์ปฌ, ์์, ์ฌ์ฉ์๋ณ ๊ฐ๋ณ์ |
| ์กฐ์ ์ ์ฝ | API ํธ์ถ์ ํตํ ์กฐํ ๋ฐ ์์ (์กฐ์์ ์ ์ฝ ์์) | ์ ์ฝ ์์ด ์์ ๋กญ๊ฒ ์กฐ์ ๊ฐ๋ฅ |
| ๋ฐ์ดํฐ ํน์ฑ | ํด๋ผ์ด์ธํธ ์์ฒญ์ ๋ฐ๋ผ ๋ณ๊ฒฝ, ๊ณต์ ๋ฐ์ดํฐ | UI ์ํ ๊ด๋ฆฌ์ ์ฌ์ฉ, ์ฌ์ฉ์ ๊ฒฝํ๊ณผ ์ง๊ฒฐ |
| ๊ด๋ฆฌ ๋ฐฉ๋ฒ | ๋ฐ์ดํฐ ์บ์ฑ์ผ๋ก ๋คํธ์ํฌ ์์ฒญ ์ต์ํ, ์๋ฒ ๋ณ๊ฒฝ ์ ์ ๋ฐ์ดํธ | useState, Redux, MobX, Context API ๋ฑ์ผ๋ก ๊ด๋ฆฌ |
| ์ํ ์ ์ง | ์ ๋ฐ์ดํธ๊ฐ ์์ผ๋ฉด out-of-date ๊ฐ๋ฅ์ฑ ์์ | ํญ์ ์ต์ ์ํ ์ ์ง |
์ต์ด ์์ฒญ ์ ์บ์๊ฐ ์์๋ : ์๋ฒ์์ ์ต์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ด
์บ์๊ฐ ์ต์ ์ํ : ์ต์ ์บ์๋ ๋ฐ์ดํฐ๋ฅผ ์ฆ์ ๋ฐ์.
์บ์๊ฐ ๋ง๋ฃ๋ ์ํ : ์ฒ์์๋ ๋ง๋ฃ๋ ๋ฐ์ดํฐ๋ฅผ ๋ฐ๊ณ , ๋ฐฑ๊ทธ๋ผ์ด๋์์ ์ต์ ๋ฐ์ดํฐ๋ฅผ ์ ๋ฐ์ดํธ
query๋ ๋ฌธ์ํ๋ค, ์ง๋ฌธํ๋ค๋ผ๋ ๋ป์ผ๋ก ํ๋ก๊ทธ๋๋ฐ์ ์ผ๋ก๋ DB์ ์ ๋ณด๋ฅผ ์์ฒญํ๋ค๋ผ๋ ๋ป์ผ๋ก ํด์ํ ์ ์๋ค.
๊ทธ๋ฌ๋ฏ๋ก TanStack-Query(๊ตฌ React-Query)๋ผ๋ ์ด๋ฆ์ DB์ ์ ๋ณด๋ฅผ ์์ฒญํ๋๊ธฐ๋ฅ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌํ ํด๋๊ฒ์ด๋ผ๊ณ ์์์ ์ผ๋ก ๋ํ๋ธ๋ค.
์๋์๋ฆฌ๋ ์๋์ ๊ฐ์ด RFC 5861์ ์ปจ์
์ ๋ฐ๋ฅธ๋ค.
Stale-While-Recalidate:
๋ฐฑ๊ทธ๋ผ์ด๋์์ stale response๋ฅผ revalidateํ๋ ๋์ ์บ์๊ฐ ๊ฐ์ง stale response๋ฅผ ๋ฐํ
StaleTime์ด ์ง๋๊ธฐ์ ๊น์ง ๋ฐ์ดํฐ๋ฅผ ๋ค์ ํธ์ถํ์ง ์๋๋ค(freshํ ์ํ).
์ง์์ ์ผ๋ก UI๋ฅผ ์ ๊ณตํ๊ธฐ ์ํด ์ต์ sever data๋ฅผ ๋ฐ์์ฌ๋๊น์ง Stale data๋ฅผ ์ฌ์ฉํ๋ค.
StaleTime : ์ผ๋ง์ ์๊ฐ์ด ํ๋ฅธ ํ์ ๋ฐ์ดํฐ๋ฅผ stale(๋ก์) ์ทจ๊ธํ ๊ฒ์ธ์ง
CacheTime : ๋ฉ๋ชจ๋ฆฌ์ ์ผ๋ง๋งํผ ์์๊ฑด์ง
Query ์ํํ๋ฆ (ํ๋ฉด์ ์๋ค๊ฐ ์ฌ๋ผ์ง๋ query)
Query ์ํํ๋ฆ (ํ๋ฉด์ ์๋ค๊ฐ ์๋ค๊ฐ ์ข ๋ ๋ณต์กํ query)
๋ด๋ถ์ ์ผ๋ก๋ Context API๋ฅผ ์ฌ์ฉํ๋ค.
์ด๋ฅผ ํตํด ์ปดํฌ๋ํธ๊ฐ์ ์ฟผ๋ฆฌ์ํ ๋ฐ ์บ์ฌ๋ฐ์ดํฐ๋ฅผ ๊ณต์ ํ ์ ์๋ค.
๐ ๊ตฌ์กฐ๋ถํดํ ๋น ๋ฌธ๋ฒ์ ์ฌ์ฉํ๋ฉด ์ ์ธํ ๋ณ์๋ฅผ ๋ชจ๋์ฌ์ฉํด์ผ๋๋ค.
GET ์์ฒญ์ ์ฌ์ฉ
function Example() {
const { isLoading, error, data } = useQuery({
queryKey: ['repoData'],
queryFn: () =>
fetch('https://api.github.com/repos/TanStack/query').then(
(res) => res.json(),
),
})
if (isLoading) return 'Loading...'
if (error) return 'An error has occurred: ' + error.message
์์ธํ ๋ด์ฉ์ useQuery์ ์ฐธ๊ณ
๋ฐ์ดํฐ ํจ์นญ์ด ํ ์ปดํฌ๋ํธ ๋ด๋ถ์์ ์ฌ๋ฌ๊ฐ ์คํ๋์ด์ผํ๋ค๋ฉด useQuery๋ฅผ ๋ณ๋ ฌ๋ก ์ ์ธํ๋ฉด ๋๋ค.
๋ณต์ ์ฟผ๋ฆฌ์ ๋ํ ๋ก๋ฉ, ์ฑ๊ณต, ์คํจ์ฒ๋ฆฌ๋ฅผ ํ๋๋ก ๊ด๋ฆฌํ๊ณ ์ถ๋ค๋ฉด useQueries๋ฅผ ์ฌ์ฉํ๋ฉด ๋๋ค.
const results = useQueries({
queries: [
{ queryKey: ['post', 1], queryFn: fetchPost, staleTime: Infinity},
{ queryKey: ['post', 2], queryFn: fetchPost, staleTime: Infinity}
]
})
POST, PUT, DELETE ์์ฒญ์ ์ฌ์ฉ
function App() {
const mutation = useMutation({
mutationFn: (newTodo) => {
return axios.post('/todos', newTodo)
},
})
return (
<div>
{mutation.isLoading ? (
'Adding todo...'
) : (
<>
{mutation.isError ? (
<div>An error occurred: {mutation.error.message}</div>
) : null}
{mutation.isSuccess ? <div>Todo added!</div> : null}
<button
onClick={() => {
mutation.mutate({ id: new Date(), title: 'Do Laundry' })
}}
>
Create Todo
</button>
</>
)}
</div>
)
}
onSuccess: () => {
queryClient.invalidateQueries({
queryKey: ['ํ๊ฒ ์ฟผ๋ฆฌํค'],
});
},
์์ธํ ์ฌํญ์ useMutation์ ์ฐธ๊ณ
https://tanstack.com/query/v4/docs/react/overview
https://velog.io/@jhjung3/1-React-Query-Overview
https://velog.io/@hyunjine/Server-State-Client-State https://velog.io/@jkl1545/React-Query
https://velog.io/@jkl1545/React-Query
https://velog.io/@jay/5-minute-react-query-essential
https://velog.io/@jay/10-minute-react-query-concept
https://techblog.woowahan.com/6339/
https://www.youtube.com/watch?v=MArE6Hy371c
https://medium.com/hcleedev/web-react-query-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0-%EB%93%B1%EC%9E%A5-%EB%B0%B0%EA%B2%BD-%EC%9E%A5%EC%A0%90-%EA%B8%B0%EC%B4%88-%EA%B0%9C%EB%85%90-e82a3733036c
https://leego.tistory.com/entry/react-query%EB%8A%94-%EC%96%B4%EB%96%BB%EA%B2%8C-%EC%9E%91%EB%8F%99%ED%95%A0%EA%B9%8C
https://tkdodo.eu/blog/inside-react-query