FrontEnd/React

React Todo에서 UX개선

여행 가고싶다 2023. 4. 28. 12:16

프론트엔드 인턴쉽에서 투두리스트 앱을 만드는 과제를 하던 중 UX를 해치는 부분을 발견했다.

 

 

// 기존 코드

const updateTodoHandler = () => {
    setIsUpdate(() => true);
    const newTodo = newTodoRef.current?.value;
    if (isInputValid(newTodo)) return;
    onUpdate(todoItem.id, newTodo, todoItem.isCompleted);
    setIsUpdate(() => false);
  };

const onUpdateTodo = async (todoId: number, todoText: string, isCompleted: boolean) => {
    await updateTodo(todoId, todoText, isCompleted);
    onReadTodo();
  };

 

 

기존

그건 바로 Todo를 업데이트할 때 깜빡인다는 것이다.

 

사실 투두리스트의 핵심 기능중 하나인 업데이트할 때 깜빡이는 버그는 꽤나 큰 문제로 다가왔는데

 

 

이 문제를 해결하기 위해선 일단 문제의 원인을 찾아야 했다.

 

 

우리의 코드는 업데이트하면 update API호출을 하고 바로 다음에 get API 호출을 한 다음에 사용자에게 보여준다.

 

이 과정에서 깜빡이게 되는건데

 

이걸 고치려면 사용자가 업데이트를 했을 때 사용자 화면에서만 바꿔주면 된다.

 

하지만 그렇게 되면 서버에서 오류가 있거나 update에 실패하게 되더라도 사용자는 인지하지 못한 채 서비스를 이용하게 된다.

 

그래서 기존 코드는 그것을 방지하기 위해서 항상 최신의 상태를 유지하려고 update후 바로 get API호출해서 다시 그린다.

 

 

이러한 문제점을 개선하기 위해 고민했는데 해결방법으로 생각해 낸 게 우선 사용자의 상태는 변경시켜 놓고, 그러고 나서 update의 API호출을 하는 것이다.

 

그렇게 되면 사용자는 즉시 수정이 반영된 상태를 볼 수 있을 것이다.

 

그렇지만 최신상태를 반영할 수 없기 때문에 API호출에서 응답으로 에러가 온다면 다시 롤백시키는 로직을 추가하거나 경고창을 띄워서 문제를 해결하면 깔끔하게 해결할 수 있을 거 같다.

 

// 개선 코드

  const updateTodoHandler = () => {
    setIsUpdate(() => true);
    const newTodo = newTodoRef.current?.value;
    if (isInputValid(newTodo)) return;
    onUpdate(todoItem.id, newTodo, todoItem.isCompleted);
    setIsUpdate(() => false);
  };

// 추가
  const updateTodoState = (todoId: number, todoText: string, isCompleted: boolean) => {
    setTodoItems((prevTodoItems) =>
      prevTodoItems.map((todo) =>
        todo.id === todoId ? { ...todo, todo: todoText, isCompleted } : todo
      )
    );
  };

  const onUpdateTodo = async (todoId: number, todoText: string, isCompleted: boolean) => {
    updateTodoState(todoId, todoText, isCompleted);
    await updateTodo(todoId, todoText, isCompleted);
    onReadTodo();
  };

 

개선

추가로 다른 팀원분이 제시한 방법이 있었는데

 

// 또 다른 개선 코드

  const updateTodoHandler = async () => {
    setIsUpdate(() => true);
    const newTodo = newTodoRef.current?.value;
    if (isInputValid(newTodo)) return;
    await onUpdate(todoItem.id, newTodo, todoItem.isCompleted);
    setIsUpdate(() => false);
  };

  const onUpdateTodo = async (todoId: number, todoText: string, isCompleted: boolean) => {
    // updateTodoState(todoId, todoText, isCompleted);
    await updateTodo(todoId, todoText, isCompleted);
    await onReadTodo();
  };

 

비동기 순서를 통제해서 호출 순서를 바꾸는 것이다.

 

이렇게 되면 업데이트 호출에 대한 응답을 받은 이후에 get으로 받은 응답을 그리기 때문에 깜빡이는 문제를 해결할 수 있다.

 

 

 

 

내가 생각한 방법도 좋지만 이러한 방법도 바로 같이 떠올릴 수 있도록 경험치를 쌓아야겠다.