안녕하세요! RyuWoong 입니다.
이번에는 React Query에 대해 조금 이야기 해볼까합니다.
사실 제가 Nextjs에 React Query 쓰면서 옛날 버전 문서보고 삽질해서 그런거 아님.
여튼 시작하시죠.
전역 상태 관리
사실 React Query를 이야기하기 전에 상태 관리 이야기부터 했어야 했을 것 같다는 생각이 드는데,
과거에 상태관리 라이브러리가 한정적인 시절 Redux는 React를 다룬다면 꼭 알아야했을 정도로 중요한 상태관리 라이브러리였습니다. (과거엔 이런 상태 개념을 익힌다는 것이 React의 진입장벽을 높인다는 이야기가 많았죠.) 그리고 전역상태관리라는 것이 왜 필요하게 됐는지에 대한 이야기를 보면 필수적인 요소로 보이구요. 무엇이든 그렇지 않겠냐만, 잘 사용하지 못하면 전역상태관리는 혼란을 만드는 요인이 됩니다. 그래서 저는 전역상태관리를 최대한 배제하는 방식을 선호합니다. 하지만 사용자의 경험 등의 이유로 전역상태를 필요로 하는 부분이 있습니다. 이는 대부분 Sever 상태(서버에서 가져온 데이터) 입니다. 서버의 데이터는 수시로 변하기 때문에 데이터를 호출하고 조금 후엔 이 데이터가 올바른 데이터인지 확신할 수 없습니다. 따라서 시간이 지나면 다시 불러오거나, 내가 가지고 있는 데이터를 갱신할 필요가 있습니다. 이를 편하게 해줄수 있는 도구가 바로 React Query 입니다. 유사한 라이브러리로 SWR도 있지만, React Query를 더 많이 사용하는 모양새여서 React Query에 대해 이야기 해볼까 합니다.
Start!
그럼 한번 직접 다뤄보도록 하겠습니다.
위 링크로 가면 간략하게 어떻게 사용하는지 코드로 짧게 설명이 되어있습니다.
사실 크게 어려운 것이 없습니다. 하나씩 보도록해볼까요? Next를 기준으로 설명드리겠습니다.
import {
useQuery,
useMutation,
useQueryClient,
QueryClient,
QueryClientProvider,
} from '@tanstack/react-query'
import { getTodos, postTodo } from '../my-api'
function App({ Component, pageProps, ...rest }: AppProps) {
const [queryClient] = useState(() => new QueryClient());
return (
// Provide the client to your App
<QueryClientProvider client={queryClient}>
<Component {...pageProps} />
</QueryClientProvider>
)
}
_App.js 파일에 위와 같이 작성해줍시다.
Quick Start에 작성된 내용과 조금 다른점이 있죠? 바로 QueryClient를 선언해주는 부분입니다.
Quick Start는 순수 React를 예제로 삼고 있습니다. React의 App.js는 첫 접속 후에 queryClient는 선언되고 그대로 유지되지만, Next.js는 페이지를 이동하게 되면 _App.js 부터 새롭게 렌더링 되는 방식이기 때문에, useState를 이용해 단 한번만 선언되게 만들어줍니다. 이렇게 하지 않으면 계속 새로운 QueryClient가 생성되고 전파되기 때문에 기존 데이터가 유실되는 상황이 발생합니다. (이거 때문에 삽질한 슬픈 사람) 이것만 주의만 해주시면, 기존 React에서 사용하던 것과 크게 다르지 않습니다.
useQuery
가장 기본적으로 사용 하는 Hook입니다. 코드를 보면서 함께 이야기해보겠습니다.
function Todos() {
// Access the client
const queryClient = useQueryClient()
// Queries
const query = useQuery({ queryKey: ['todos'], queryFn: getTodos })
// Mutations
const mutation = useMutation({
mutationFn: postTodo,
onSuccess: () => {
// Invalidate and refetch
queryClient.invalidateQueries({ queryKey: ['todos'] })
},
})
return (
<div>
<ul>
{query.data?.map((todo) => (
<li key={todo.id}>{todo.title}</li>
))}
</ul>
<button
onClick={() => {
mutation.mutate({
id: Date.now(),
title: 'Do Laundry',
})
}}
>
Add Todo
</button>
</div>
)
}
Query Key
QueryKey는 고유한 키입니다. React Query는 해당 키로 값을 불러오고 저장합니다. String도 가능하고 Array형태도 가능하지만 좀 더 고유한 키를 원하신다면, 아래와 같은 키를 생성할 수 도 있습니다.
const query = useQuery({ queryKey: ['todos',{done:true}], queryFn: getTodos })
쿼리키는 해쉬처리하여 저장되거나 비교 합니다. 위 같이 작성한다면, 상태 값에 따라 리스트를 저장 해 둘 수 있겠죠?
하지만 주의해야할 점은, Tuple형태로 작성할 때 입니다. 이 때는 값 순서를 지켜주셔야합니다.
// 이는 튜플이지만 두번째 상태들이 Object로 저장되어 순서에 신경쓰지 않고 값여부에 신경 쓰면 되지만,
const query = useQuery({ queryKey: ['todos',{done, now}], queryFn: getTodos })
// 튜플 형태로 나열된다면, 순서까지 신경써야한다.
const query = useQuery({ queryKey: ['todos',done, now], queryFn: getTodos })
QueryFn
Query Function은 단순합니다. 서버와 통신하여 데이터를 받아오는 비동기 함수를 넣어주시면 됩니다.
맨 위 코드를 보면 getTodos라는 함수를 넣어줘서 Todo List를 서버로 부터 받아오는 함수를 넣어줬습니다.
result
useQuery를 사용하면 다양한 값을 리턴해주는데요. 크게 Data와 Status를 제공합니다.
Data는 말그대로 서버에서 받아온 Data이고, Status는 현재 Loading 중인지, Error가 발생했는지, Success 성공적으로 잘 데이터를 받아왔는지를 알 수 있습니다. 이것을 이용하면 예외처리를 편안하게 할 수 있습니다.
Stale Time, CacheTime
그리고 중요한 것이 이 두 시간 설정입니다.
Stale Time은 데이터가 언제까지 '신선'한가에 대한 기준이고, Cache Time은 얼마나 오래 '기억'하고 있는가에 대한 기준입니다.
Stale Time
예를 들어 Stale Time의 기본 값은 0인데 이는 useQuery가 해당 키로 실행될 때 서버에서 항상 다시 받아오는 것을 의미합니다. 만약 5분이라면 5분 동안은 서버에서 받아오지 않고 기존에 가지고 있는 값을 그대로 보여줍니다.
CacheTime
예를 들어 CacheTime의 기본 값은 5분인데, unMount 되어서 inActivate가 되면 카운트가 됩니다.
5분이 지나면 가비지 콜렉터가 캐시데이터를 지웁니다. 만약 캐시가 지워지기 전에 Mount 된다면 데이터가 fetch 되는 동안 Cache되어 있던 Data를 보여줍니다.
끝.
대략적인 중요한 내용은 여기까지 인거 같습니다.
추가적으로 활용도가 높은 다른 함수들은 useMutation, useInfinityQuery 등이 있을거 같습니다.
만약 시간이 된다면 다른 활용도가 높은 함수들도 포스팅 해보도록 하겠습니다.
요새는 서버 상태를 React Query를 이용하여 관리하거나, GrapQL을 사용하는 방식을 많이 사용하는 것 같습니다.
다음은 GrapQL을 공부해야겠습니다! 그럼 다음 포스팅에서 뵙겠습니다.
'Front-End > Next.js' 카테고리의 다른 글
[Next] Data Fetching .02 (0) | 2023.02.28 |
---|---|
[Next] Routing .01 (0) | 2023.01.29 |
[Next] 시작하기 .00 (0) | 2023.01.18 |
삽질의 기록과 일상을 남기는 블로그입니다. 주로 React Native를 다룹니다.
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!