api요청을 한 후 새롭게 적용된 데이터를 보여줘야할 때, 우리가 생각하는 것보다 늦게 데이터가 반영된다.
이를 해결하기 위해 api 요청을 하면서 ui를 미리 반영하는 낙관적 업데이트라는 것을 한다.
대표적인 예로 좋아요 클릭 시 하트 색 또는 좋아요 개수를 변경시키는 것이 있다.

(gif가 좀 이상하게 잘려서 아다리가 안맞음 ㅠ;) 이렇게 좋아요를 클릭해도 숫자가 늦게 반영이 되는 상황에서 낙관적 업데이트를 사용하면 좋아요를 클릭 시 개수를 바로 반영시킬 수 있다.
낙관적 업데이트 방법
(두둥)
일단 나는 react-query를 사용하고 있고, 좋아요 클릭 시 post 요청을 보내고 있다.
1. useMutate의 onMutate에서 변경하고자 하는 쿼리를 queryClient.cancelQueries 한다.
좋아요 버튼을 클릭하면서 동일한 쿼리의 데이터가 요청될 수 있다. 이 경우 낙관적 업데이트한 데이터를 덮어씌울 수 있으므로(race condition) 그 요청 결과가 캐시를 덮어씌우지 못하도록 막는다.
onMutate: async () => {
await queryClient.cancelQueries({ queryKey: ['comment', idx] });
2. queryClient.getQueryData로 해당 쿼리 데이터를 받는다.
const cache = queryClient.getQueryData(['comment', idx]);
3. 캐시에 map을 돌려 같은 idx의 경우 좋아요 값과 개수 값을 변경해준다.
const copy = cache?.map(i => {
if (i.IDX === IDX) {
return {
...i,
IS_LIKE: !prevIsLike ? 1 : 0,
LIKE_CNT: !prevIsLike ? i.LIKE_CNT + 1 : i.LIKE_CNT - 1,
};
}
return i;
});
4. 변경한 copy 데이터를 queryClient.setQueryData에 넣어준다. 그리고 캐시데이터를 onMutate에서 리턴해준다. 이 리턴해준 데이터는...
queryClient.setQueryData(['comment', idx], { copy });
return { cache };
}
5. onError의 context에 담기게 된다. 만약 에러가 날 경우 onError에서 setQueryData로 context의 해당 데이터를 가져다 사용하여 롤백되도록 한다.
onError: (err, _, context) => {
if (context?.cache) {
queryClient.setQueryData(['comment', idx], context.cache);
}
},
이렇게 낙관적 업데이트를 한 후의 결과

흐린눈을 하려면 할 수 있는 사항이지만 좋은 UX를 위해서는 이런 사소한 디테일을 챙기는 것 또한 중요한 것 같다
'React' 카테고리의 다른 글
| [react-router] CSR, SSR, loader, HydrationBoundary (framwork) (0) | 2026.08.07 |
|---|---|
| js를 ts로 변환하기(리액트 프로젝트) (4) | 2026.01.09 |
| react-hook-form을 알아보자 (2) | 2025.08.13 |
| useState에서 상태 변경 시 바로 재렌더링 일어나지 않는 버그 (2) | 2025.08.13 |
| throttle과 debounce 사용하기 (2) | 2025.06.21 |