optimistic-ui

이재홍·2022년 6월 22일
0

https://story.pxd.co.kr/1193

낙관적 Optimistic

optimistic-ui

optimistic-ui 란 단어 그대로 낙관적인! UI 임.
요청 결과가 오류가 나지 않을 것을 미리 예상하고 사용자애개 성공 시 결과를 바로 보여주는 것이다.
그것도 실제 요청 결과가 나오기 전에 말이다.

요청이 올 때까지 기다리는 대신 먼저 UI를 변경해두고, success response 가 오지 않을 경우에는 에러처리 or 롤백 처리를 하여서 UI를 수정한다.

주의사항: 혹시 모를 에러에 대한 로직을 작성해 두지 않는다면 사용자 입장에서는 분명 요청이 성공된 것으로 봤는데 실제로는 실패한 상황인 것을 보게 된다.

EX)

import { gql, useMutation, useQuery } from "@apollo/client";

const FETCH_BOARD = gql`
  query fetchBoard($boardId: ID!) {
    fetchBoard(boardId: $boardId) {
      _id
      likeCount
    }
  }
`;

// 좋아요 카운트 올리는 api
const LIKE_BOARD = gql`
  mutation likeBoard($boardId: ID!) {
    likeBoard(boardId: $boardId)
  }
`;

export default function OptimisticUIPage() {
  const [likeBoard] = useMutation(LIKE_BOARD);
  const { data } = useQuery(FETCH_BOARD, {
    variables: { boardId: "62b3c48d03610b0029990501" },
  });

  const onClickLike = () => {
    likeBoard({
      variables: {
        boardId: "62b3c48d03610b0029990501",
      },
      // 응답을 받고난 후 받아온 응답을 다시 fetch 해줍니다.
      //  -> 느리고 효율적이지 못합니다.(백엔드에 요청을 한번더 해야하고 받아올때 까지 기다려야 합니다.)
      // refetchQueries: [
      //   {
      //     query: FETCH_BOARD,
      //     variables: { boardId: "62b3c48d03610b0029990501" },
      //   },
      // ],

      // 옵티미스틱 UI -> 캐시를 바꾸고 캐시값을 받아오는걸 기다리지 않고 바로 바꿔줌
      // 현재 좋아요 수  + 1 , 만약에 좋아요가 없다면 0으로.
      optimisticResponse: {
        likeBoard: (data?.fetchBoard.likeCount || 0) + 1,
      },

      // apollo 캐시를 직접 수정을 할 수 있었습니다.(백엔드 캐시가 아닙니다.) -> 느리지만 효율적
      update(cache, { data }) {
        cache.writeQuery({
          query: FETCH_BOARD,
          variables: {
            boardId: "62b3c48d03610b0029990501",
          },
          // id,__typename 가 반드시 들어가야한다.
          data: {
            fetchBoard: {
              likeCount: data.likeBoard,
              _id: "62b3c48d03610b0029990501",
              __typename: "Board",
            },
          },
        });
      },
    });
  };

  return (
    <>
      <h1>옵티미스틱 UI</h1>
      <div>현재 카운트(좋아요): {data?.fetchBoard.likeCount}</div>
      <button onClick={onClickLike}>조항요!!</button>
    </>
  );
}

refetch를 통해 완료 요청이 왔을때 화면을 그려줬지만 optimisticResponse 를 이용해 apollo clientoptimistic 버전으로 저장되면 apollo client 가 이를 보고 저장된 데이터를 가지고 연관되어 있는 컴포넌트들을 재랜더링한다.

이제 진짜 실제 완료요청 데이터를 받으면 apollo client는 기존의 버전을 지우고 서버에서 받은 데이터를 저장하고 적용한다! (그후 재랜더링)

0개의 댓글