찍찍이 #타인 프로필 페이지 (Optimistic Update)

박기범·2025년 1월 9일
0

다음으로 진행했던 페이지는 타인 프로필 페이지이다.
아 페이지는 검색으로 나왔던 상대방의 아이콘을 클릭했을때 이동하는 페이지이고
상대방의 인증내역을 사진으로 볼 수 있다.

크게 기능은 유저 프로필 및 인증 내역 불러오기, 팔로우 기능이 있다.


유저 프로필 및 인증 내역 불러오는 api는 기존의 방법 처럼 쿼리 custom hooks를 통해 한 파일로 관리하였음.

...

const userProfileOptions = (
  userId: number,
): UseQueryOptions<UserProfileResponse, AxiosError> => ({
  queryKey: [QUERY_KEYS.USER_PROFILE, userId],
  queryFn: () =>
    GET<UserProfileResponse>(API_ENDPOINTS.AUTH.USER_PROFILE(userId)),
});

export const useUserProfileQuery = (userId: number) => {
  const { data, isLoading } = useQuery(userProfileOptions(userId));
  const name = data?.data.name;
  const profilePic = data?.data.profilePic;
  const isFollow = data?.data.isFollow;
  const completeResponses = data?.data.completeResponses ?? [];
  return { name, profilePic, isFollow, completeResponses, isLoading };
};

다음으로 팔로우 기능은 기존의 인스타그램의 팔로우 방식을 따랐다.
팔로우 기능의 로직은 React-Query의 useMutation과 Optimistic Update를 활용하여 FID 개선을 이루었음. 사용자가 팔로우 버튼을 클릭하면 네트워크 요청 완료 전에 UI가 바로 업데이트되어 반응성을 높이고, 실패 시 상태를 복구. 이를 통해 사용자는 빠르고 즉각적인 인터페이스를 경험 가능.

FID (First Input Delay): 사용자가 페이지와 처음으로 상호작용한 시점(클릭, 탭, 키 입력 등)부터 브라우저가 이벤트 핸들러 실행을 시작하기까지 걸린 시간을 측정한 지표
다시 말하자면 페이지가 사용자의 입력에 응답하는데 걸리는 시간

코드 설명은 다음과 같다.
실행되는 동안 현재 boolean 타입의 팔로우 값을 임시로 true값으로 바꾼 다음 변수값에 쿼리데이터를 저장. 성공 여부와 상관없이 쿼리 데이터를 업데이트를 해주고 실패시에는 저장한 변수를 다시 set하는 방식이다.

...

export const useAssignFollowMutation = () => {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: (userId: number) =>
      POST<AssignFollowResponse, FollowId>(
        API_ENDPOINTS.FOLLOW.ASSIGN_FOLLOW(userId),
      ),
    onMutate: async (userId) => {
      const previousData = queryClient.getQueriesData<UserProfileResponse>({
        queryKey: [QUERY_KEYS.USER_PROFILE, userId],
      });

      await queryClient.cancelQueries({
        queryKey: [QUERY_KEYS.USER_PROFILE, userId],
      });

      queryClient.setQueryData(
        [QUERY_KEYS.USER_PROFILE, userId],
        (oldData: UserProfileResponse) => ({
          ...oldData,
          data: {
            ...oldData.data,
            isFollow: true,
          },
        }),
      );
      return { previousData };
    },
    onSettled: (userId) => {
      queryClient.invalidateQueries({
        queryKey: [QUERY_KEYS.USER_PROFILE, userId],
      });
    },
    onSuccess: () => {
      notify('success', '팔로우 등록', 3000);
    },
    onError: (error, userId, context) => {
      queryClient.setQueryData(
        [QUERY_KEYS.USER_PROFILE, userId],
        context?.previousData,
      );
      console.error(error.message);
      notify('error', '팔로우 등록 실패', 3000);
    },
  });
};

개발자 도구의 성능분석 탭을 통해서 녹화를 하여
낙관적 업데이트의 성능을 분석해보았다. (FID)

낙관적 업데이트를 적용하지 않은 코드 -> 약 0.4초가 걸림.
낙관적 업데이트를 적용한 코드 -> 약 0.2초가 걸림.
https://web.dev/articles/fid?hl=ko 해당 공식 사이트를 참고하여 측정하였고

profile
프론트엔드 개발공부를 하고있습니다.

0개의 댓글

관련 채용 정보