Optimistic UI

hyeseon han·2021년 10월 23일
0
post-custom-banner

기존의 UI 인터랙션

UI(User Interface)

사용자와 정보기기나 소프트웨어의 화면 등 상호작용을 위한 장치

인터랙션

사용자가 제품이나 서비스를 사용하면서 상호간 작용하는 과정

예시로 자유게시판 상세보기에서 좋아요 버튼을 눌렀을 때를 생각해보자.

async function onClickLike() {
    await likeBoard({
      variables: { boardId: "6138031babd89b00293ae454" },
      // refetch될 때까지 기다린다.
      refetchQueries: [
        {
          query: FETCH_BOARD,
          variables: { boardId: "6138031babd89b00293ae454" },
        },
      ],
    });
    alert("좋아요를 클릭합니다.");
  }
  1. 사용자가 좋아요 버튼을 누른다.
  2. onClick 함수 실행되고 서버에 mutation 요청을 보낸다.
  3. 서버에 보낸 요청이 완료될 때까지 await으로 기다린다.
  4. 완료됐다는 응답이 오면 이제 refetch해서 좋아요 갯수 데이터를 다시 가져온다.
  5. 가져온 데이터를 화면에 보여준다.

버튼을 클릭하고 사용자는 결과를 얻기위해 많은 과정을 걷쳐서 기다려야한다.


옵티미스틱(Optimistic) UI

낙관적인 예측을 하는 UI이다. 서버로부터 받는 응답은 대부분 오류가 나지 않을 것이다. 성공적일 것이다라고 가정하고 사용자에게 성공했을 때의 결과를 바로 보여준다. 중요한 데이터에는 사용하면 안된다.

  1. 사용자가 좋아요 버튼을 누른다.
  2. 좋아요 갯수가 1개 증가한 UI를 바로 보인다.
  3. 서버에 mutation을 요청한다.
  4. 서버에서 응답을 받는다.

오류가 발생했을 경우

성공할거라고 예상했는데, 뒤늦게 서버에서 에러가 났다는 응답이 오면 조용히 원래 상태로 되돌린다.

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

	...

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

  const onClickLike = () => {
    likeBoard({
      variables: { boardId: "6138031babd89b00293ae454" },
      // optimisticResponse: graphQL에서 mutation을 할 때 제공하는 옵션.
      optimisticResponse: {
        likeBoard: data?.fetchBoard.likeCount + 1,
      },
      update(cache, { data }) {
        cache.writeQuery({
          query: FETCH_BOARD,
          variables: { boardId: "6138031babd89b00293ae454" },
          data: {
            fetchBoard: {
              // _id, __typename 반드시 적어야한다. 
              _id: "6138031babd89b00293ae454",
              __typename: "Board",
              likeCount: data.likeBoard,
            },
          },
        });
      },
    });
  };

  return (
    <>
      <div>좋아요 갯수: {data?.fetchBoard.likeCount}</div>
      <button onClick={onClickLike}>좋아요 올리기!!</button>
    </>
  );
}
  1. likeBoard 함수가 실행 될 때, optimisticResponse에 적은 내용이 apollo-client-cache에 optimistic 버전으로 따로 저장된다.
  2. apollo-client는 이를 알아차려 저장된 데이터를 가지고 연관된 컴포넌트들을 다시 렌더링한다. 이 때, 네트워크 요청이 필요없으로 사용자들에게 거의 바로 반영된다.
  3. 서버에서 진짜 데이터를 응답으로 받으면, apollo-client는 기존의 optimistic 버전을 지우고 서버에서 받은 데이터를 저장한다.
  4. apollo-client는 다시 이를 알아차리고 연관된 컴포넌트를 다시 렌더링 한다.
post-custom-banner

0개의 댓글