React Query를 프로젝트에 도입한 이후,
가장 체감이 컸던 부분은 비동기 요청의 상태를 눈으로 바로 확인할 수 있게 된 것이었습니다.
하지만 그 상태가 화면에만 머물면,
정작 사용자는 아무런 피드백을 받지 못합니다.
버튼을 눌렀는데 아무 일도 안 일어나는 듯한 상황,
“잘 눌린 건가?” 싶은 그 2~3초의 공백이 UX를 망칩니다.
그래서 이번에는 React Query와 Toast 알림 시스템을 연결해
사용자에게 명확한 피드백을 주는 방법을 정리해봤습니다.
단순한 기능이지만 체감은 확실하다
처음 React Query를 썼을 땐, 로딩 스피너 하나면 충분하다고 생각했습니다.
그런데 사용자가 서버 응답을 기다리는 동안
무언가 ‘눈에 띄는 반응’이 없으면
“버그인가?” “멈췄나?” 같은 불안감을 느끼는 걸 자주 봤습니다.
실무에서 가장 많이 쓰는 해결책이 바로 Toast입니다.
보통 react-hot-toast나 sonner, notistack 같은 라이브러리를 많이 씁니다.
저는 주로 react-hot-toast를 선호합니다.
설치는 간단합니다.
yarn add react-hot-toast
루트 컴포넌트(App)에 Provider를 추가해두고,
원하는 위치에서 toast.success()나 toast.error()로 호출하면 끝입니다.
React Query와 자연스럽게 묶는 법
React Query는 onSuccess, onError 훅을 제공합니다.
여기서 Toast를 바로 호출하면,
서버 응답에 따라 실시간으로 메시지를 띄울 수 있습니다.
import { useMutation } from '@tanstack/react-query';
import toast from 'react-hot-toast';
import axios from 'axios';
function useCreateUser() {
return useMutation({
mutationFn: (data) => axios.post('/api/users', data),
onSuccess: () => toast.success('사용자가 성공적으로 등록되었습니다!'),
onError: (err) => toast.error(`등록 실패: ${err.message}`),
});
}
이걸 폼과 연결하면,
사용자가 버튼을 눌렀을 때 즉시 로딩 상태가 보이고,
결과가 도착하는 순간 명확한 피드백이 주어집니다.
별다른 상태 변수를 추가하지 않아도 되는 점이 특히 마음에 듭니다.
이런 부분에서 진짜 체감했다
이 조합의 진가는 실패 상황에서 드러납니다.
예전에는 에러가 나면 그냥 콘솔에 찍히거나
화면 어딘가에 조그맣게 ‘오류 발생’ 정도가 뜨는 수준이었죠.
그런데 지금은 toast.error('로그인이 만료되었습니다. 다시 로그인해주세요.')
한 줄이면 바로 눈에 띄게 경고를 띄울 수 있습니다.
최근에 작업했던 사내 관리 페이지에서도
API 토큰 만료 시 이런 메시지를 띄워줬는데,
덕분에 QA팀 피드백이 “에러 상황이 훨씬 명확해졌다”로 바뀌었습니다.
그 전까진 “버튼 눌렀는데 아무 반응이 없어요”가 단골 민원이었습니다.
의외로 중요한 세밀한 부분들
토스트를 띄울 때 가장 많이 하는 실수가
모든 요청마다 중복 알림을 띄우는 것입니다.
서버 요청이 3번 반복되면 토스트도 3개가 뜨는 경우가 있죠.
저는 이 문제를 해결하기 위해 toast.dismiss()를 먼저 호출하거나,
id를 지정해서 중복 알림을 방지했습니다.
toast.loading('처리 중...', { id: 'processing' });
// ...
toast.success('완료되었습니다!', { id: 'processing' });
이렇게 하면 기존 알림이 갱신되면서
중복되지 않고 한 줄로 이어집니다.
이런 작은 디테일이 전체 경험을 깔끔하게 만듭니다.
결국 중요한 건 “사용자 입장”
개발자 입장에서는
로딩 상태나 성공 여부가 눈에 보이지만,
사용자는 코드나 콘솔을 볼 수 없습니다.
화면과 피드백이 전부입니다.
React Query와 Toast를 결합하면
개발자는 단순히 API 요청을 관리할 뿐인데
사용자는 “즉각적이고 명확한 시스템 반응”을 경험하게 됩니다.
이 차이가 곧 서비스의 완성도를 결정짓는다고 생각합니다.
다음 글에서는 React Query의 캐싱을 활용해
화면 전환 시에도 데이터가 깜빡이지 않게 유지하는 방법을 다뤄보겠습니다.
로딩을 숨기는 게 아니라,
‘이미 있는 데이터’를 영리하게 재활용하는 접근입니다.
이건 실무에서 체감 효과가 정말 큽니다.