SWR 사용법

Jin·2022년 3월 31일
0

React

목록 보기
15/17

SWR은 Next.js로 유명한 Vercel에서 만든 원격 데이터 가져오기를 위한 Hook입니다.

오직 useSWR이라는 훅을 사용하여 데이터를 조작합니다.

useSWR

const { data, error, isValidating, mutate } = useSWR(key, fetcher, options)

파라미터

  • key: 요청을 위한 고유한 값
  • fetcher: 데이터를 조작하기 위한 함수를 반환하는 프라미스
  • options: SWR의 옵션 객체

결과값

  • data: fetcher가 가져온 데이터
  • error: fetcher가 던진 에러
  • isValidating: 요청이나 갱신 여부
  • mutate: POST, PUT과 같이 데이터를 추가하거나 갱신할 때 사용

옵션

  • suspense = false: React Suspense 모드를 활성화
  • fetcher(args): fetcher 함수
  • revalidateIfStale = true: automatically revalidate even if there is stale data (details)
  • revalidateOnMount: 컴포넌트가 마운트되었을 때 자동 갱신 활성화 또는 비활성화
  • revalidateOnFocus = true: 창이 포커싱되었을 때 자동 갱신
  • revalidateOnReconnect = true: 브라우저가 네트워크 연결을 다시 얻었을 때 자동으로 갱신(navigator.onLine을 통해)
  • refreshInterval:
    기본적으로는 비활성화: refreshInterval = 0
    If set to a number, 인터벌 폴링
    If set to a function, the function will receive the latest data and should return the interval in milliseconds
  • refreshWhenHidden = false: 창이 보이지 않을 때 폴링(refreshInterval이 활성화된 경우)
  • refreshWhenOffline = false: 브라우저가 오프라인일 때 폴링(navigator.onLine에 의해 결정됨)
  • shouldRetryOnError = true: fetcher에 에러가 있을 때 재시도
  • dedupingInterval = 2000: 이 시간 범위내에 동일 키를 사용하는 요청 중복 제거
  • focusThrottleInterval = 5000: 이 시간 범위 동안 단 한 번만 갱신
  • loadingTimeout = 3000: onLoadingSlow 이벤트를 트리거 하기 위한 타임아웃
  • errorRetryInterval = 5000: 에러 재시도 인터벌
  • errorRetryCount: 최대 에러 재시도 수
  • fallback: 다중 폴백 데이터의 키-값 객체 (예시)
  • fallbackData: 반환될 초기 데이터(노트: hook 별로 존재)
  • onLoadingSlow(key, config): 요청을 로드하는 데 너무 오래 걸리는 경우의 콜백 함수(loadingTimeout을 보세요)
  • onSuccess(data, key, config): 요청이 성공적으로 종료되었을 경우의 콜백 함수
  • onError(err, key, config): 요청이 에러를 반환했을 경우의 콜백 함수
  • onErrorRetry(err, key, config, revalidate, revalidateOps): 에러 재시도 핸들러
  • compare(a, b): 비논리적인 리렌더러를 회피하기 위해 반환된 데이터가 변경되었는지를 감지하는데 사용하는 비교 함수. 기본적으로 dequal을 사용합니다.
  • isPaused(): 갱신의 중지 여부를 감지하는 함수. true가 반환될 경우 가져온 데이터와 에러는 무시합니다. 기본적으로는 false를 반환합니다.
  • use: 미들웨어 함수의 배열

데이터 가져오기

const [value, setValue] = useState("");
const [currentPage, setCurrentPage] = useState(1);

const get = async (keyword: string, currentPage: number) => {
  if (keyword.trim() === "") {
    return {
      total: -1,
      juso: [],
    };
  }

  const res = await jusoApi.get("", {
    params: {
      keyword,
      currentPage,
    },
  });

const { data, isValidating } = useSWR(
  [value, currentPage],
  () => get(value, currentPage),
  {
    revalidateIfStale: false,
    revalidateOnFocus: false,
    revalidateOnReconnect: false,
    dedupingInterval: 10 * 1000, // 10 sec
  }
);

제가 useSWR을 사용하여 데이터를 가져온 코드입니다.
첫번째 인자로 value와 currentPage가 담긴 배열을 담습니다. 이렇게 되면 만약 10초 안에 같은 value와 currentPage로 호출했다면 API 호출을 하지 않고 캐시에 있는 데이터를 사용합니다.

dedupingInterval에서 stale time을 10초로 설정하였기 때문입니다.

두번째 인자로 fetcher를 설정해줍니다.
get이라는 함수는 value와 currentPage를 받아서 axios로 API에 호출을 합니다.

세번째 인자로 옵션을 설정해줍니다.
위에서 설명한대로 필요한 옵션을 가져다가 설정해주면 됩니다.

POST 요청

useSWR에는 mutate라는 결과값이 있습니다. 이걸 활용하여 데이터를 조작할 수 있습니다.

const { data, mutate } = useSWR("submit", () => post(state));

const post = async (state: IState) => {
  if (!state.phoneNumber) {
    return {};
  }

  const res = await caredocApi.post("/application", state);
  return res.data;
};

useEffect(() => {
  (async () => {
    const res = await mutate(state);
    // 받은 res의 데이터 중 _id로 POST 조회 가능
  })();
}, [state.phoneNumber]);

저의 경우에는 전역 상태로 관리하는 state의 phoneNumber라는 요소가 변경되면 mutate를 통해서 POST 요청을 보내도록 하였습니다.

사용법은 GET 요청일 때와 거의 비슷합니다.
첫 번째 인자로 키를, 두 번째 인자로 fetcher를 넣어줍니다.

옵션은 여기서 필요하지 않으므로 생략하였습니다.

이렇게 결과값으로 받은 mutate를 사용하면 이미 키, fetcher 등이 모두 바인딩되어 있는 상태이기 때문에 따로 어떤 추가 설정이 필요없습니다.
그저 올바른 인자를 넣어주고 호출만 하면 됩니다.

느낀 점

리액트 쿼리와 SWR 둘 다 사용해보았는데 가볍게 요청을 보낼 목적이라면 SWR을, 세부적으로 설정을 해야 할 필요가 있다면 리액트 쿼리가 낫겠다는 생각을 하였습니다.

참고

https://swr.vercel.app/ko/docs/getting-started

profile
배워서 공유하기

0개의 댓글