API를 요청하면서 페이지를 이동 할때 API가 작동하지 않는 문제

김동현·2023년 11월 29일
0

이슈 일기

목록 보기
5/6

문제상황
개별 알림 처리 기능을 작업 하고 있었다. 내가 원하던 동작은 알림 카드를 클릭 할 시 알림 리스트가 업데이트 되고 나서 내 물건 제안 페이지로 이동하는 것이었다. 처음 몇번의 동작은 의도한 대로 동작하는 듯 싶었다. 그러나 몇번 더 테스트를 해 본 결과 간헐적으로 페이지가 이동만 되면서 업데이트는 되지 않는 문제가 발생했다. 아래는 해당 문제가 발생했던 코드이다. 원래도 간단한 코드지만 핵심적인 부분만 남겨놓았다.

const handleReadNotification = () => {
	mutate(알림아이디, 카드아이디)
  	router.push(이동 페이지)
}

mutate 함수는 useNotificationUpdateMutation이 반환하는 함수이다.

useNotificationUpdateMutation = () => {
  const router = useRouter()
  const queryClient = useQueryClient()
  const queryKey = ['notifications', false]
  return useMutation({
    mutationFn: async ({
      notificationId,
    }: {
      notificationId: number
      cardId: number
    }) => {
      // 생략
      await putNotificationList({ notificationIds })
    },

    onSettled: () => {
      queryClient.invalidateQueries({
        queryKey,
      })
    },

useNotificationUpdateMutation은 putNotificationList라는 API 함수를 호출하고 쿼리 인스턴스의 상태를 무효화(invalidate)하여 새로운 리스트를 다시 fetch하도록 하고 있다.

원인
위 코드의 문제점은 코드의 실행 순서를 보장 할 수 없다는 점이다. handleReadNotification에 정의된 내용으로만 봐서는 mutate가 호출되고나서 push가 호출되었으니 예상한 동작을 할 것 처럼 보인다. 그러나 문제는 mutate는 비동기적으로 작동한다는 것이다. 따라서 router.push가 먼저 호출이 되어도 이상할게 없다. 아마 간헐적으로 리스트가 업데이트 되지 않았던 부분도 mutate가 빠르게 처리 될때는 정상 동작하지만 느리게 처리 될때는 동작 수행중 페이지가 이동하면서 함수의 동작이 끊긴게 아닌가 싶다. 아래 그림은 위 설명을 뒷받침한다.

해결방법
useMutation에서 실행순서를 보장하기 위해서는 onSuccess 옵션에 해당하는 동작을 수행하는 이벤트 핸들러를 넣어주면 된다. onSuccess 옵션은 API가 정상적으로 동작한 이후에 넣어준 이벤트 핸들러를 호출시킨다.

const handleReadNotification = () => {
	mutate(알림아이디, 카드아이디)
}
useNotificationUpdateMutation = () => {
  const router = useRouter()
  const queryClient = useQueryClient()
  const queryKey = ['notifications', false]
  return useMutation({
    mutationFn: async ({
      notificationId,
    }: {
      notificationId: number
      cardId: number
    }) => {
      // 생략
      await putNotificationList({ notificationIds })
    },

    onSettled: () => {
      queryClient.invalidateQueries({
        queryKey,
      })
    },
    onSuccess: () => {
      router.push(이동 페이지)
    }

위와 같이 코드를 이동 시킨 후 테스트를 해 본 결과 항상 리스트를 업데이트 시킨 직후에만 페이지를 이동하는것을 확인 할 수 있었다.

profile
有備無患 : 미리 대비하고 있으면 걱정할 일이 없다

0개의 댓글