Frontend/swr

swr을 이용하여 fetcher call 횟수를 효율적으로 줄이기

개발하는루루 2024. 9. 8. 22:48

API 콜은 네트워크 비용을 지불한다. 의도치 않게 불필요한 API 콜은 서버의 부하도 증가시켜 필요한 응답의 시간을 증가시킨다. 

비용 지불 관점 외에도 앱의 응답 속도가 저하되어 UX도 악화될 수 있다.

 

swr은 기본적으로 hook 내에서 마운트 되거나 focus되면 API를 실행시킨다.

사실 컴포넌트를 마운트한 이후에 필요에 따라서만 업데이트 해도 좋다.

 

자주 변하지 않는 값의 경우 앱을 킨 후, 한번만 사용하여 캐싱된 값만 사용할 수도 있고

어떤 화면은 포커싱될 때마다 일정 주기마다 업데이트 되길 기대할 수 있다.

 

즉, 마운트될 때마다 실행될 필요가 있는지, 포커싱될 때마다 실행될 필요가 있는지를 검토해주면 좋다. 

 

SWR은 revalidatieOnMountrevalidatieOnFocus 옵션을 제공한다. default는 true다.

그렇기때문에 의도치 않게 컴포넌트가 마운트/언마운트를 반복해서 여러번 fetch하는 경험을 할 수 있다. 

 

1. 앱 실행 이후 한번만 실행되어도 되거나, 특정 한 순간에만 update해도 된다면 아래와 같이 사용하면 좋다. 

=> revalidatieOnMount = false, revalidatieOnFocus = false, mutate 함수 활용하기.

  const { mutate } = useSWR(
    ["load-holding-tokens", accountModel, chainID],
    async ([_, _accountModel, _chainID]) => {
      if (!_accountModel || !_chainID) return;
      await TokenController.initialLoadHoldingTokens(_accountModel);
    },
    {
      revalidateOnFocus: false,
      revalidateOnMount: false,
    }
  );

 

이렇게 정의해두면 key change에 따른 revalidate도 가능하고, 원하는 순간에 mutate도 가능하다.

 

2. 화면에 포커싱 될때만 업데이트 하도록 하기

=> 포커스여부 함수 활용하여 key를 null이 되거나 의도한 값이 담기도록 한다. 

컴포넌트가 마운트 된 이후에 특정 인터벌동안 api가 호출될 수 있다. 포커싱이 되지 않아도 마운트가 되었다면 계속 호출될 수 있는데 이럴 경우엔 아래와 같이 작성해주면 좋다. 

 

  const {
    data: amount,
    mutate,
    error,
  } = useSWR(
    isFocused ? ["palm-staked-amount", chainID, blockNumber, address] : null,
    async ([, _chainID, _blockNumber, _address]) => {
      if (!_address || !_blockNumber || !_chainID) return undefined;
      return PalmStakingController.getStakedAmount(_address);
    },
    {
      keepPreviousData: true,
      onError: () => {
        mutate(undefined, false);
      },
    }
  );

 

포커싱이 되지 않으면 key를 null로 하면 어떤 key가 바뀌더라도 fetcher가 동작하지 않게된다.

특정 key에 따라 change될 때마다 업데이트가 되지만 이는 화면에 포커싱될 때만 실행되도록 하기 위해선 위와 같이 작성해주면 좋다.