게시글의 '좋아요'버튼을 누를 때, 서버에 도달하기 전에
화면의 값을 바꿔버리는 옵티미스틱 UI를 사용하게 된다.
API요청을 하기도 전에 화면상에서 값을 바꿔버리고 계속해서 요청을 보내는 것이다.
❗️옵티미스틱UI는 보통 실패 확률이 낮고 만일 실패하더라도, 큰 상관이 없을 때 사용한다.
데이터가 굉장히 중요하고 안정성이 필요할 때는 옵티미스틱을 사용하면 안된다!
import { gql, useMutation, useQuery } from "@apollo/client";
import {
IMutation,
IMutationLikeBoardArgs,
IQuery,
IQueryFetchBoardArgs,
} from "../../src/commons/types/generated/types";
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 { data } = useQuery<Pick<IQuery, "fetchBoard">, IQueryFetchBoardArgs>(
FETCH_BOARD,
{
variables: {
boardId: "6399abb2531bd200286b7781",
},
}
);
const [likeBoard] = useMutation<
Pick<IMutation, "likeBoard">,
IMutationLikeBoardArgs
>(LIKE_BOARD);
const onClickLike = () => {
void likeBoard({
variables: { boardId: "6399abb2531bd200286b7781" },
// refetchQueries: [{ query: FETCH_BOARD, variables : { boardId : "6399abb2531bd200286b7781"} }],
optimisticResponse: {
likeBoard: (data?.fetchBoard.likeCount ?? 0) + 1,
// 서버에서 실제로 값을 받아오기 전에, 서버의 응답을 기다리지 않고 가짜로 응답을 받았다고 속이고 미리 보여주는 것.
},
// refetch하게 되면 다시한번 렌더링을 해야하므로, update로..
update: (cache, { data }) => {
cache.writeQuery({
// modify는 수정만 할 수 있었다면, writeQuery는 기존에 없던 것도 새롭게 작성 할 수 있음.
query: FETCH_BOARD,
variables: { boardId: "6399abb2531bd200286b7781" },
data: {
fetchBoard: {
_id: "",
__typename: "Board", // id와 typename이 굉장히 중요⭐️
likeCount: data?.likeBoard, // 좋아요 올라간 수
},
},
});
},
});
};
return (
<>
<div>현재카운트(좋아요): {data?.fetchBoard.likeCount}</div>
<button onClick={onClickLike}>좋아요 올리기!!</button>
</>
);
}
옵티미스틱 UI를 적용하면 컴퓨터 환경에 상관없이 유저 모두가 빠른 서비스를 이용하는 것 같이 속일 수 있다!