기존의 UI
예를 들어 자유게시판 상세보기에서 '좋아요👍' 버튼을 누를 때의 동작을 생각해보면 다음과 같다.
- 사용자가 👍 버튼을 누른다.
- onClick 함수가 실행되고 서버에 mutation 요청을 보내게 된다.
- 서버에 보낸 요청이 완료될 때까지 await으로 기다린다.
- 완료됐다는 응답이 오면 이제 refetch를 해서 좋아요 갯수 데이터를 다시 가져온다.
- 가져온 데이터를 화면에 보여준다.
좋아요 버튼 하나 클릭했을 뿐인데, 사용자는 결과를 얻기까지 기다려야한다. 또한 몰입하고 있는 상태를 방해하게 된다. 이를 해결하기 위한 방법이 Optimistic UI 이다.
Optimistic UI
단어 그대로 낙관적으로 생각하는 UI이다. 서버로부터 받는 응답이 대부분 오류가 나지 않고 성공적일 것이라고 가정하고 사용자에게 성공했을 때의 결과를 바로 보여주는 것이다.
- 사용자가 👍 버튼을 누른다.
- 좋아요 갯수가 1개 증가한 UI를 바로 보여준다.
- 서버에 mutation을 요청한다.
- 서버에서 응답을 받는다.
오류가 발생했을 경우
성공할거라고 예상했는데, 서버에서 뒤늦게 에러가 났다는 응답이 오면 조용히 원래 상태로 되돌린다.
중고마켓에서 찜하기 버튼을 생각해봅시다.
- 사용자가 찜하기 🤍 버튼을 누른다.
- 💛 버튼 색상이 바뀌면서 찜이 되었음을 바로 알려준다.
- 서버에 요청한다.
- 서버에서 실패했다는 응답을 받는다.
- 조용히 찜하기 버튼의 🤍색깔을 변경한다.
이렇게 함으로써 에러가 났다는 경고창으로 인해 사용자는 뜬금없이 방해 받을 일도 없고, 색상이 다시 변경되었기 때문에 다시 시도 해야겠다는 생각을 자연스럽게 하게 된다.
그래프큐엘에 적용하기
그래프큐엘에서는 mutation을 할 때 [optimisticResponse] 라는 옵션을 제공한다.
const [updateComment] = useMutation(UPDATE_COMMENT);
const onClickComment = () => {
updateComment({
variables: { commentId, commentContent },
optimisticResponse: {
updateComment: {
id: commentId,
__typename: "Comment",
content: commentContent,
},
},
});
};
- updateComment 함수가 실행이 될 때, 우리가 optimisticResponse 에 적은 내용이 아폴로 클라이언트 캐시에 optimistic 버전으로 따로 저장된다.
- 아폴로 클라이언트는 이를 알아차려 저장된 데이터를 가지고 연관된 컴포넌트들을 다시 랜더링한다. 이 부분은 네트워크 요청이 필요없기 때문에 사용자들에게 거의 바로 반영된다.
- 서버의 응답으로 진짜 데이터를 받으면, 아폴로 클라이언트는 기존의 optimistic 버전을 지우고 서버에서 받은 데이터를 저장한다.
- 아폴로 클라이언트는 다시 이를 알아차리고 연관된 컴포넌트를 다시 랜더링한다.
Optimistic UI
Optimistic UI is a pattern that you can use to simulate the results of a mutation and update the UI even before receiving a response from the server. Once the response is received from the server, the optimistic result is thrown away and replaced with the
www.apollographql.com
댓글