02. Tanstack Query 데이터 작성하기

flee | 플리·2026년 3월 22일

recode-TanstakQuery

목록 보기
2/3
post-thumbnail

1편에서 useQuery로 서버 데이터를 "읽는" 방법에 대해 설명해봤는데요!
이번 편에서는 서버 데이터를 "쓰는" 방법에 대해 알아보겠습니다~
게시글 작성,수정, 삭제처럼 서버에 변경을 요청하는 모든 작업에 참고하시면 됩니다!!

0. Intro

1편의 이론을 간단히 정리하면 아래와 같습니다.
▶ 1편 이동하기

이번 편에서는 데이터를 직접 쓰고(POST), 제어(수정(PUT,PATCH), 삭제(DELETE))하는 방식에 대해 알아보겠다.

추가적으로 아래 요소들도 함께 다뤄보겠다.


1. useMutation이란?

서버 데이터를 생성(POST), 수정(PUT, PATCH), 삭제(DELETE)할 때 사용하는 훅
즉, 데이터를 "쓰는" 훅이다.

1-1. useQuery와 차이점

useQuery는 컴포넌트가 렌더링되면 자동으로 실행된다.
하지만, useMutation은 버튼 클릭, 폼 제출처럼 "특정 이벤트가 발생했을 때" 실행된다.

1-2. useMutation 기본 구조

  • mutationFn : 실제 API 요청을 담당하는 함수. Promise를 반환하면 된다.
  • onSuccess : 요청이 성공했을 때 실행되는 콜백. 응답 데이터(data)를 인자로 받는다.
  • onError : 요청이 실패했을 때 실행되는 콜백. 에러 객체(error)를 인자로 받는다.
  • onSettled : 성공/실패 여부와 상관 없이 항상 실행되는 콜백. try-catchfinally와 동일 개념

참고
Tanstack Query 공식 문서

1-3. useMutation 반환값

useMutation이 반환하는 주요 값들은 아래와 같다.

  • mutate : mutation을 실행하는 함수. 이벤트 핸들러에서 호출한다.
  • isPending : 요청 진행 중 여부 (boolean값)
  • isError : 에러 발생 여부 (boolean값)
  • error : 에러가 발생한 객체

반환값 사용 방식은 두 가지이다.

상황에 맞게 편한 방식을 선택하여 사용하면 된다.

참고
mutatemutateAsync 두가지가 있다.

  • mutate : 콜백(onSuccess, onError) 방식으로 결과 처리
  • mutateAsync : Promise를 반환하여 async/await으로 결과 처리


    Tanstack Query 공식 문서

useMutation 선언과 반환값의 전체 코드는 다음과 같다.

1-4. 예제 코드

게시글을 작성하는 POST 요청 예제이다.

위의 예시코드의 작동 화면이다.


2. useQueryClient란?

QueryClient 인스턴스에 접근하여 캐시를 직접 제어하는 훅

지난 글에서 QueryClient는 모든 캐시를 저장하는 핵심 인스턴스라고 설명했다.
useQueryClient는 해당 인스턴스에 접근하여 캐시를 읽거나 수정할 수 있게 해준다.

use로 시작하니, React의 Hook개념이 베이스인거 잊지말기!

위와 같은 방식으로 선언하여 사용한다.

참고
Tanstack Query 공식 문서

2-1. invalidateQueries : 캐시 무효화

특정 Query Key의 캐시를 "오래된 것(stale)"으로 표시하여 자동으로 재요청 유발

mutation으로 데이터를 변경했을 때, 기존 캐시가 최신 데이터를 반영하지 못하는 상황이 발생한다.
invalidateQueries를 호출하면, 해당 캐시를 stale 처리하고, 화면에서 사용 중인 경우 자동으로 재요청하여 최신 데이터로 갱신한다.

참고
Tanstack Query 공식 문서

2-2. setQueryData : 캐시 직접 수정

특정 Query Key의 캐시 데이터를 직접 수정.
API 재요청 없이 캐시를 업데이트 할 때 사용한다.

invalidateQueries는 서버에 재요청하여 최신 데이터를 받아오는 방식이라면,
setQueryData는 서버 요청 없이 캐시만 직접 수정한다.

주로 낙관적 업데이트(4. 낙관적 업데이트)에서 사용된다.

참고
Tanstack Query 공식 문서

2-3. 예제 코드

게시글 작성 후 목록 캐시를 갱신하는 실제 코드이다.

onSuccess에서 invalidateQueries를 호출하면,
게시글 작성 성공 후 자동으로 목록을 다시 불러온다.


3. 에러 핸들링

3-1. onError 콜백

mutation 실패 시 onError 콜백에서 에러를 처리할 수 있다.

참고
onSettledmutation 상태(성공, 실패)와 무관하게 모두 실행된다.
캐시 무효화처럼 결과에 관계없이 항상 실행해야 하는 로직은 onSettled에 두는 것이 좋다.

3-2. isError/error 반환값 활용


isErrorerror를 활용하면, UI에서 직접 에러 상태를 표시할 수 있다.

위의 예시코드를 구현한 화면이다.

4. useMutation + useQueryClient 함께 사용하는 패턴

4-1. 낙관적 업데이트(Optimistic Update)란?

서버 응답을 기다리지 않고, 요청이 성공할 것이라 '낙관'하고 UI를 먼저 업데이트 하는 패턴

일반적인 요청 흐름과 비교한다면 다음과 같다.

일반적인 흐름

요청 → (대기) → 서버 응답 → UI 업데이트

낙관적 업데이트 흐름

요청 → UI 즉시 업데이트 → 서버 응답 → (실패 시 rollback)

서버 응답을 기다리는 동안 UI가 멈춰있지 않기 때문에 사용자 경험(UX)이 향상된다.
인스타그램의 좋아요 버튼이 대표적인 예시이다.
버튼을 누르는 즉시 하트가 채워지고, 실패 시에만 원래대로 돌아온다.

4-2. onMutate + onError rollback 흐름

낙관적 업데이트는 onMutate, onError, onSettled 세 콜백을 조합하여 구현한다.

  • onMutate : 요청 직전. 현재 캐시를 백업하고, UI를 먼저 업데이트
  • onError : 요청 실패. 백업해둔 캐시로 rollback
  • onSettled : 요청 완료 후. 서버 데이터와 최종 동기화(invalidateQueries)

4-3. 예제 코드

실제 게시글 스크랩 버튼 기능을 낙관적 업데이트로 구현한 코드이다.

참고
cancelQueries란? (onMutateawait 부분)
진행 중인 refetch 요청을 취소한다.
낙관적 업데이트 직전에 호출하지 않으면, 진행 중이던 refetch 응답이 낙관적으로 업데이트한 캐시를 덮어쓸 수 있다.

해당 코드를 실제로 구현하면 아래와 같이 작동한다.

5. 마무리..

이번 글에서 다룬 내용을 정리하면 아래와 같다.

  • useMutation 으로 서버 데이터를 생성, 수정, 삭제한다.
  • onSuccess, onError, onSettled 콜백으로 요청의 성공, 실패, 완료 시점을 처리한다.
  • useQueryClientinvalidateQueries로 캐시를 무효화하여 목록을 자동 갱신한다.
  • useQueryClientsetQueryData로 서버 요청 없이 캐시를 직접 수정한다.
  • onMutate + onError rollback 패턴으로 낙관적 업데이트를 구현한다.

이제 Tanstack Query의 핵심은 파악했다!
( 하지만 배움의 축복은 끝나지 않는다... 공식 문서에 축복들이 잔뜩 있다.. )

다음편에서는 지금까지의 이론을 바탕으로 Next.js 환경에서 자동 저장 기능을 직접 구현한 과정을 작성해 볼 예정이다.

참고
▶ 🔗 Tanstack Query 공식 문서

profile
바라는 색이 있다면 눈이 멀도록 바라볼 것. 가능한 온몸으로 부서질 것.

0개의 댓글