본문 바로가기

개발자 강화/프론트엔드

[매일메일] 낙관적 업데이트란? (FE.250121)

낙관적 업데이트

성공적인 상태 업데이트가 이루어 질 것이라는 가정 하에 서버 응답 전 UI를 미리 업데이트 해둠.

 

대표적인 예시 - 좋아요 기능

사용자가 좋아요 버튼을 눌렀을 때, 서버 응답을 기다리지 않고 화면에 바로 버튼 누름 상태 반영함.

서버 응답이 성공적으로 돌아오면 유지하고, 실패하면 UI에서 해제하거나 오류 메시지를 보여줌

 

장점

서버 응답 속도와 상관 없이 즉각적인 피드백을 제공해서 사용자가 시스템을 빠르게 쓸 수 있음

네트워크 상태가 좋지 않거나 응답 시간이 길어도 사용자 경험에 영향이 덜 미침

 

단점

서버에서 오류가 발생하면 잠시동안 화면에 잘못된 정보가 표시될 수 있음

이를 대비해 오류 핸들링(rollback) 로직을 같이 설계해줘야 함

 

낙관적 업데이트를 사용해야 하는 경우

요청이 성공할 가능성이 높고, 사용자 경험을 즉시 개선하는 게 큰 장점이 있을 때

- SNS 좋아요 누른 후 결과 반영 등

const mutation = useMutation({
  mutationFn: (newComment) =>
    fetch('/api/comments', {
      method: 'POST',
      body: JSON.stringify(newComment),
    }),
  onMutate: async (newComment) => {
    await queryClient.cancelQueries(['comments']); // 기존 요청 취소

    const previousComments = queryClient.getQueryData(['comments']);

    queryClient.setQueryData(['comments'], (old) => [...old, newComment]);

    return { previousComments };
  },
  onError: (error, newComment, context) => {
    // 실패 시 롤백
    queryClient.setQueryData(['comments'], context.previousComments);
  },
  onSettled: () => {
    queryClient.invalidateQueries(['comments']); // 쿼리 무효화
  },
});

 

TanStack Query의 useMutate로 낙관적 업데이트 구현
- POST, PUT, DELETE 등 데이터를 서버에 전송하거나 변경 작업을 수행할 때 사용
onMutate 변경 작업 서버 응답 전 UI 즉시 업데이트 또는 실패 시 롤백 위한 값 반환
(낙관적 업데이트+rollback) 응답을 onError나 onSettled에서 사용 가능
useMutate의 state
mutate, 변경 작업을 실행하는 함수
mutateAsync, 비동기로 변경 작업 실행
isLoading, 작업 중인지 여부
isError, 오류 발생 여부
error, 발생한 오류 객체
isSuccess, 작업 성공 여부
data, 작업 성공 시 반환된 데이터
onSuccess 변경 작업 성공 서버에서 반환된 데이터를 사용해 캐시 업데이트
onError 변경 작업 실패 onMutate 반환 값을 사용해 rollback 처리
onSettled 변경 작업 성공/실패 후
항상 호출
쿼리 데이터 무효화하거나 UI 상태 초기화
서버-데이터 동기화 해 최신 상태 유지하기 위해 항상 실행
서버 응답 상관 없이 동일한 후처리가 필요할 때 항상 실행

 

 

낙관적 업데이트를 사용하면 안되는 경우

1. 중요한 데이터를 다루는 경우

- 결제, 거래 내역 등 비즈니스 로직과 밀접하게 연결 된 부분

- 요청에 실패한다면 민감도가 높은 정보가 순간적으로 잘못 표시되며 사용자 경험을 크게 저해할 수 있음

- 만약 장바구니 상품 결제를 낙관적 업데이트로 처리했지만, 서버 요청에서 문제가 생긴 경우

   장바구니 상품을 결제함->낙관적 업데이트로 UI에서 상품 먼저 삭제->결제 완료 후 장바구니 이동->아직 장바구니 state update 결과가 서버에서 도착하지 않아 결제 전으로 UI rollback 되어 있음-> 사용자는 결제했는데도 장바구니에 남아있는 상품을 발견함 -> ???

2. 네트워크 환경이 불안정한 경우

- 요청에 대한 실패율이 높아져 rollback이 자주 일어남. 사용자는 내 행동이 반영이 안되는 경험을 반복해 만족도 낮아짐.

- 서버 응답을 기다리는 로직이 오히려 사용자 경험을 증진시킬 수 있음.

 

출처

[1] 매일메일. 250121. 낙관적 업데이트에 관하여 설명해주세요. 55번. https://maeil-mail.kr

[2] 낙관적 업데이트로 사용자 경험을 개선해보자! 

https://tecoble.techcourse.co.kr/post/2023-08-15-how-to-improve-ux-with-optimistic-update/

[3] gpt에게 TanStack Query - useMutate에 대해 묻다