optimistic-ui

유연희·2022년 6월 29일
0

optimistic-ui

optimistic-ui는 특정 요청이 높은 확률로 성공 할 것이라는 가정 하에 결과를 먼저 보여주는 방식의 UI이다.

예들 들어 페이스북의 좋아요 버튼을 누르는 상황을 생각해보면,
사용자는 좋아요 버튼을 누르자 마자 버튼의 이미지와 숫자가 즉각적으로 바뀐다고 느끼게 된다. 이때 (1)좋아요 버튼을 누르면 (2)백엔드에 좋아요를 1개 올리라는 api에 요청을 보내게 되고, (3)백엔드는 DB에 요청을 보내 좋아요를 1증가시킨 후에 (4)브라우저는 백엔드로부터 응답을 받아 UI를 수정하게 된다. 이처럼 좋아요 버튼에도 상당히 많은 데이터 요청과 응답이 발생한다. 이때 느린 컴퓨터 환경 혹은 백엔드 컴퓨터와의 거리 등의 여러 환경적인 문제로 백엔드로부터 응답을 받기까지의 시간이 지연될 수 있는데, 이때 응답이 올때까지 기다렸다가 UI를 바꾸게 되면 사용자가 불편함을 느낄 수 있다. 이런 경우에 응답이 도착하지 않은 상태에서도 성공 응답이 도착할 것이라는 가정 하에 버튼의 모양과 개수를 미리 바꿔주어 사용자의 입장에서는 불편함을 느끼지 못하도록 만들어 주는 방법이 optimistic-ui이다.

사용 예시코드

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

//좋아요 갯수 가지고 오는 api _ 게시글 조회 api에서 좋아요 갯수만 뽑아 옵니다. 
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(){
    const [likeBoard] = useMutation(LIKE_BOARD)
    const { data } = useQuery(FETCH_BOARD,
                                                        {variables :{boardId : "게시글 아이디 넣어주세요!"} })

  const onClickOptimisticUI = ()=>{
      likeBoard({
          variables :{
              boardId : "게시글 아이디"
          },

      // refetch를 이용하는 경우 백엔드에 요청을 한번더 해야하고 받아올때 까지 기다려야 한다.
      //refetchQueries: [
      //	{
      //		query: FETCH_BOARD,
      //		variables : {	boardId : "//게시글 아이디" }
      //	}
      // ]

      //옵티미스틱 UI -> 캐시를 바꾸고 캐시값을 받아오는걸 기다리지 않고 바로 바꿔준다.
      optimisticResponse: {
          likeBoard : (data?.fetchBoard.likeCount || 0)+1
      },
          update(cache,{data}){
              cache.writeQuery({
                  query : FETCH_BOARD,
                  variables : {boardId:'게시글 아이디 넣어주세요!'}
                  //어떻게 수정할 것인지는 아래에 적어줍니다.
                  data: {
                      fetchBoard: {
                          _id : '게시글 아이디 넣어주세요!',
                          __typename : "Board"
                          likeCount: data?.likeBoard
                      }
                  }
              })
          }
      })
  }

  return(
      <div>
              <h1>옵티미스틱 UI</h1>
              <div>현재카운트(좋아요):{data.fetchBoard.likeCount}</div>
              <button onClick={onClickOptimisticUI}>좋아요 올리기!!</button>
      </div>
  )

}

profile
developer

0개의 댓글