Tanstack Query는 상태 관리를 하는 라이브러리중 하나입니다.

공식문서를 보면 제일 먼저 보이는 문구입니다.
무슨 뜻일까요?
"TS/JS, React, Vue, Solid, Svelte, Angular 애플리케이션을 위한 강력한 비동기 상태 관리, 서버 상태 유틸리티 및 데이터 가져오기(Data Fetching) 도구"
라고 소개를 하고 있습니다.
우리가 클라이언트를 구축할 때의 상태는 크게 2가지로 나눌 수 있습니다.
기존의 상태 관리 도구는 '클라이언트 상태'를 관리하기에는 좋지만
'서버 상태'를 관리할때는 문제가 많았습니다.
tanstack query를 사용하지 않으면 개발자는 로딩 상태, 에러 상태, 데이터 저장을 하나하나 다 직접 구현해야 합니다.
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
fetch('/api/posts')
.then(res => res.json()) .then(setData)
.catch(setError)
.finally(() => setLoading(false));
}, []);
useState useEffect try-catch 등 보일러플레이트가 너무 깁니다.const ReactQueryPage = () => {
const fetchPosts = () => {
return axios.get('http://localhost:3004/posts')
}
const {data, isLoading, error} = useQuery({
queryKey: ['posts'],
queryFn: fetchPosts,
retry: 3,
select: (data) => {
return data.data
}
})
해당 코드의 동작 결과는

이렇게 나옵니다 짜잔~
마운트 : 페이지 컴포넌트가 화면에 나타난다. 데이터 확인 : [’posts’]라는 키로 저장된 캐시 데이터가 있는지 확인한다. 요청 시작 : isLoading이 true가 되고, 화면에는 “로딩 중” 이 뜨며 동시에 fetchPosts가 실행된다. 데이터 도착캐싱 : 가져온 데이터는 메모리에 캐싱된다. 만약 Tanstack Query를 사용하지 않은 상태에서 다른 페이지로 이동을 하고 다시 원래 페이지로 돌아온다고 가정을 해봅시다.
그럼 서버에서 데이터를 가져와야 합니다.
위와 같은 동작이 반복된다면 어떤 문제가 있을까요?
등과 같은 문제점이 발생할 수 있습니다.
캐싱은 한 번 가져온 데이터를 메모리에 저장해 두었다가,
같은 데이터가 필요할 때 서버에 다시 요청하지 않고 저장된 값을 재사용하는 것입니다.
Q : 그렇다고 캐시가 있으면 API 호출을 아예 안 하는가?
A : 아닙니다. 캐시가 있어도 API를 호출합니다.
하지만 로딩 대신에 캐시된 데이터를 미리 보여주며 뒤에서는 API 호출 작업을 하고
호출이 완료되면 다시 업데이트를 진행합니다.

staleTime 과 gcTime은 목적과 작동 시점이 다릅니다
staleTime : 상한 상태gcTime : 쓰레기통 시간Tanstack Query는 데이터 변경 작업(생성, 수정, 삭제 등)을 위한 useMutation 훅을 제공합니다.
이를 통해, 데이터 변경 작업을 처리하고 다양한 성공, 실패, 로딩 등의 상태를 얻을 수 있습니다.
그리고 요청 실패 시의 자동 재시도나 낙관적 업데이트 같은 고급 기능도 쉽게 처리할 수 있습니다.
useQuery는 가져오기, useMutation는 보내기에
export const useCreatePost = () => {
// 1. 쿼리 클라이언트 가져오기
const queryClient = useQueryClient()
return useMutation({
// 2. 실제로 수행할 작업 (서버 요청)
mutationFn: (member: string) => {
return axios.post('http://localhost:3004/posts', { member })
},
// 3. 성공 시 실행할 로직 (Side Effect)
onSuccess: () => {
// 4. 'posts'라는 키를 가진 쿼리를 무효화(invalidate) 시킴
queryClient.invalidateQueries({ queryKey: ['posts'] })
},
})
}
useQueryClient()useMutation 자체는 데이터 수정만 담당합니다. 수정이 끝난 뒤 이미 캐시 되어 있는 다른 데이터(['posts'])를 건드릴때 권한이 필요하기 때문입니다.mutationFnaxios.post를 사용해 서버에 member 데이터를 담아 보냅니다.mutate("훈진")라고 호출하면, 여기서 member 변수에 "훈진"이 들어옵니다.onSuccess : 성공시 처리mutationFn이 에러 없이 성공적으로 끝났을 때만 실행되는 함수로 데이터 변경이 성공한 직후에 무엇을 할지 정의합니다.queryClient.invalidateQueries({ queryKey: ['posts'] })invalidateQueries는 ['posts']라는 이름표 붙은 데이터 상했어(Invalid). 버려~" 라고 말합니다.useQuery를 재실행(Refetch)합니다.
Tanstack Query는 최근 간단하게 사용해보기는 했지만, 글을 읽으면서 전반적으로 사용 방법과 개념들을 정리할 수 있어서 좋았습니다. 모든 기술들을 사용할 때에는 명확한 이유가 있어야 한다고 생각하는데, 기존 코드에서는 어떠한 문제점이 있었고, Tanstack Query를 사용하면 이러한 문제들에 대해서 어떤 장점을 얻을 수 있는지 알 수 있었습니다.
특히 Tanstack Query의 라이프 사이클을 기준으로 각 상태가 어떤 의미인지 설명되어 있어서 조금 더 쉽게 이해할 수 있었던 것 같습니다. 추후 Tanstack Query를 사용할 때에는 누군가, 그리고 어디선가 사용했던 코드를 보고 작성하는 것이 아니라, 해당 코드가 명확히 어떤 의미이고 어떤 역할을 하는지 인지한 후 사용하는 것이 중요할 것 같습니다.