티스토리 뷰

🚀 낙관적 업데이트 ?

리액트 쿼리는 get 요청은 useQuery를 통해 했었고, 이외 post, update, delete 요청은 useMutation으로 처리했었습니다. 그런데 이전에 구현했던 react-query 글에서 post 요청을 하고 get 요청 했었던 쿼리를 inValid 시키고 했었습니다. 즉, 다시말해서, post 요청을 보내고 다시 get 요청을 보내고 받아서 화면에 보여줘야 한다는 점이었습니다.

 

사용자 입장에서 생각해보면, 내가 post 요청 보내는 버튼을 눌렀는데 안에서는 post 요청 보내고 ~ get 요청 했었던 거 inValid 하게 해서 다시 요청 보내게끔 하고 ~ 다시 받아오고 ~ 화면에 뿌리고 ~ 하는 작업이 이뤄져야 하고 이걸 사용자가 다 기다려야 한다는 점입니다.

 

그래서 다른 방법으로 낙관적 업데이트가 나오게 되었는데요!

여기서 낙관적 업데이트서버의 데이터를 업데이트 하기 전에 미리 화면의 UI를 바꿔준 후, 서버와의 통신 결과에 따라 확정/롤백을 결정하는 업데이트 방식을 말합니다.

쉽게 말해, 좋아요를 누르면 일단 즉시 화면에 좋아요가 눌린 화면이 반영하고, 서버에서 요청의 성공 유무에 따라 다시 데이터를 출력시킵니다. 즉, 일단 데이터가 업데이트 됐다고 생각하고 화면에 반영해서 낙관적 업데이트라고 불리는 것 같습니다 :)

😀 낙관적 업데이트

낙관적 업데이트는 onMutate를 통해 서버로 보내지는 것을 가로채서 업데이트 후에 수정사항을 보내게 됨으로 속도가 더 빠릅니다. 따라서 캐시가 더 빨리 업데이트된다는 장점이 있습니다. 왜나하면 캐시를 업데이트하기 위해 서버의 응답을 기다릴 필요가 없기 때문인데요. 단, 한가지 단점은 서버 업데이트가 실패했을 경우에 실행되는 코드가 복잡하다는 것입니다.

 

Updates from Mutation Responses | TanStack Query Docs

When dealing with mutations that update objects on the server, it's common for the new object to be automatically returned in the response of the mutation. Instead of refetching any queries for that item and wasting a network call for data we already have,

tanstack.com

onSuccess

useMutation의 onSuccess 콜백에 이제 낙관적 업데이트할 로직을 작성해 주면 됩니다. 참고로, onSuccess는 말 그대로  api 요청이 성공된 이후에 실행될 콜백함수입니다. 먼저 코드를 작성해 봅시다.

const useUpdateTodo = () => {
  const client = useQueryClient();
  
  return useMutation(({ id, data }) => TodoApi.updateTodo(id, data), {
    onSuccess: (res) => {
      client.cancleQueries([QUERY_KEY.GET_TODO]);
      client.setQueryData([QUERY_KEY.GET_TODO], (oldData) => {
        let updateData = oldData.data.find(
          data => data.id === res.data.id
        );
        updateData.content = res.data.content;
        updateData.state = res.data.state;
        return oldData;
      })
    }
  })
}
export default useUpdateTodo;

전체 코드는 위와 같고 한줄한줄 살펴봅시다 !

1. res

onSuccess: (res) => { ... }

위 코드에서 onSuccess는 말로 설명하면 res는 todo를 업데이트하는 api 요청이 성공된 이후의 응답값에 해당합니다. 보통 update하고서의 응답값으로는 업데이트가 반영된 데이터를 응답값으로 받게 됩니다. 따라서 지금 res에는 내가 수정한 데이터가 담겨 있을 것입니다.

2. client.cancleQueries()

client.cancleQueires([QUERY_KEY.GET_TODO])

낙관적 업데이트한 데이터를 덮어쓰지 않기 위해 쿼리를 수동적으로 삭제합니다. react-query에서 쿼리는 Map이라는 자료구조로 저장이 되어있습니다. 즉, key와 value로 관리가 되고 있습니다. 즉 다시말해서, 쿼리 키를 통해서 client에 캐싱되어 있는 데이터를 삭제합니다. 참고로, 캐싱 데이터를 삭제할 뿐 재요청을 보내지 않습니다.

3. client.setQueryData()

client.setQueryData([QUERY_KEY.GET_TODO], (oldData) => {
  let updateData = oldData.data.find(
    data => data.id === res.data.id
  );
  updateData.content = res.data.content;
  updateData.state = res.data.state;
  return oldData;
})

clinet.setQueryData는 지워진 공간에 낙관적으로 성공할 결과값을 다시 세팅해주는 과정이 포함되어 있습니다. setQueryData 즉, 쿼리 데이터를 set한다의 의미를 가지고 있습니다. oldData는 낙관적 업데이트를 하기 전의 데이터를 의미합니다. 따라서 res를 통해 받은 업데이트가 적용된 데이터를 가지고 화면에 지금 있는 oldData를 업데이트함으로써 바로 화면을 구성하는 것입니다.

728x90
LIST
250x250
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2026/01   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
글 보관함