[Codecamp-Week7] Optimistic-UI

·2022년 8월 23일
0
post-custom-banner

8주차에 적어보는 7주차에 배운 Optimistic UI!
Optimistic UI를 배우고 처음으로 든 생각은 '이런게 선의의 거짓말이 아닐까?' 였다!

Optimistic-UI를 사용하지 않는 상황과 Optimistic-UI를 사용하는 상황을 비교하여 Optimistic-UI가 필요한 이유를 알아보자!

1. Optimistic-UI란?

Optimistic-UI란 서버로부터 응답을 받기 전에 변환 결과를 시뮬레이션하고 UI를 업데이트하는 데 사용할 수 있는 패턴이다.
서버로부터 응답이 수신되고 나면, Optimistic-UI 결과는 버려지고 실제 서버 응답의 결과로 대체된다.

이렇게 텍스트만으로 보면 굉장히 어려운 이야기 같으니 기존 서버 응답 결과를 보여주는 상황과 Optimistic-UI를 보여주는 상황을 게시물 좋아요 기능 예시를 통해 비교하여 살펴보자!

2. 서버 응답 결과 화면과 Optimistic-UI 비교하기

(1) 기존 화면

  1. 좋아요를 누르면 백엔드에 likeBoard API 요청을 보내고
  2. 백엔드는 DB에 해당 정보를 요청하게 된다.
  3. DB는 좋아요 수를 올려두고, 올린 좋아요 수를 응답해준다.
  4. 해당 응답을 백엔드는 다시 브라우저에 응답해준다.

해당 과정은 보통의 빠른 컴퓨터에선 아무런 불편함을 느끼지 못하지만, 느린 환경의 컴퓨터에선 좋아요를 누른 후 한참 후에 숫자가 올라갈 수 있다.

(2) Optimistic-UI

  1. 좋아요를 누르면 백엔드에 likeBoard API 요청을 보내기 전에 기존 좋아요수 + 1을 미리 화면에 그려 보여준다.
  2. 이후 백엔드에 likeBoard API 요청을 보내고, 백엔드는 DB에 해당 정보를 요청하여 DB 좋아요 수를 올려두고 올린 좋아요 수를 응답해준다.
  3. 해당 응답을 화면에 업데이트 해준다. (유저 입장에서는 같은 값을 화면에서 보고 있으므로 변화를 인지할 수 없다.)

백엔드에게 API 요청을 보내기 전에 예상되는 값을 미리 보여줌으로써 유저는 빠른 사용자경험을 할 수 있다.
만약 중간에 네트워크 등의 문제로 백엔드 요청이 실패할 경우 이전 값을 응답받아 이전 값을 화면에 업데이트 해준다.

3. Optimistic-UI 사용 주의사항

Optimistic-UI는 실패 확률이 낮고 틀려도 괜찮은 중요하지 않은 데이터를 보여줄 때 사용한다.
어드민 페이지에서의 고객명단, 결제 후 잔여 금액 등 데이터가 굉장히 중요하고 안정성이 필요할 땐 Optimistic-UI를 사용해선 안된다.

4. Optimistic-UI 사용하기

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

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

const LIKE_BOARD = gql`
  mutation likeBoard($boardId: ID!) {
    likeBoard(boardId: $boardId)
  }
`;

export default function OptimisticUIPage() {

  const router = useRouter()
  
  const { data } = useQuery(FETCH_BOARD, {
    variables: { boardId: router.query.boardId },
  });

  const [likeBoard] = useMutation(LIKE_BOARD);

  const onClickLike = () => {
    likeBoard({
      variables: { boardId: router.query.boardId },
      //   Optimistic UI 설정 (가짜로 보여주는 미리보기 데이터)
      optimisticResponse: {
        likeBoard: (data?.fetchBoard.likeCount || 0) + 1,
      },
      // 2. cache 직접 수정 (OptimisticResponse에서 받은 값 data로 바꿔준 후, backend에서 data를 받아오면 받아온 진짜 data로 수정)
      update(cache, { data }) {
        cache.writeQuery({
          query: FETCH_BOARD,
          variables: { boardId: router.query.boardId },
          data: {
            fetchBoard: {
              // id, typename은 필수입력
              _id: router.query.boardId,
              __typename: "Board",
              likeCount: data.likeBoard,
            },
          },
        });
      },
    });
  };

  return (
    <>
      <div>현재 좋아요 카운트: {data?.fetchBoard.likeCount}</div>
      <button onClick={onClickLike}>좋아요 올리기</button>
    </>
  );
}

<참조: https://www.apollographql.com/docs/react/v2/performance/optimistic-ui/>

profile
개발을 개발새발 열심히➰🐶
post-custom-banner

0개의 댓글