본문 바로가기

FrontEnd/React

SWR

 

실습: https://github.com/dhflekddy/React-and-ReactHookPractice/commit/1f12eb529ddf3fe278b0dd961c8c91c0321a46ad

mutate를 이용한 Optimistic UI:  https://steadily-worked.tistory.com/565

 

useSWR, mutate에 대하여:  https://velog.io/@code-bebop/SWR-%EC%8B%AC%EC%B8%B5%ED%83%90%EA%B5%AC

useSWRInfinite에 대하여: https://velog.io/@code-bebop/SWR-%EC%8B%AC%EC%B8%B5%ED%83%90%EA%B5%AC-useSWRInfinite

https://moon-ga.github.io/swr/1-what-is-swr/

 

 

                                          SWR깃헙: https://github.com/vercel/swr(Readme.md꼭보기)

https://www.youtube.com/watch?v=b7Uqx7NZpHw

 

요약: SWR이란? "Stale-While-Revalidate"재확인 하는 동안은 구식의 상태를 가지는" 라이브러리.

SWR(Stale-While-Revalidate)은 내장된 캐시를 제공하여 이전에 가져온 데이터를 저장하고 재사용할 수 있어서 가져온 데이터를 따로 저장하는 스토어 작업도 필요 없어 코드의 양도 많이 줄 일 수 있다. 결제나 주문 정보 같은 실시간으로 보여줘야 하는 데이터들을 서버로부터 새로운 데이터가 도착하면 자동으로 화면에 반영해 실시간 경험도 제공할 수 있어서 이번에 SWR을 사용하면서 데이터 가져오기와 관련된 작업을 훨씬 쉽게 처리할 수 있었다.

React 컴포넌트에서 사용할 수 있는 훅 형태의 SWR 라이브러리이다. SWR을 사용하면 간편하게 데이터를 가져오고, 캐시 하여 이전 데이터를 재사용하며, 신선한 데이터를 가져와서 사용자 경험을 향상할 수 있다고 한다.

SWR이란?(React Query의 경쟁자)

SWR은 Stale-While-Revalidate의 약자로, React 컴포넌트에서 사용할 수 있는 훅 형태의 SWR 라이브러리이다. SWR을 사용하면 간편하게 데이터를 가져오고, 캐시 하여 이전 데이터를 재사용하며, 신선한 데이터를 가져와서 사용자 경험을 향상할 수 있다고 한다.

 

SWR의 역할은 크게 두 가지이다.

  1. 서버로의 데이터 요청 시점 컨트롤
    데이터를 언제 요청할 것인지 컨트롤 하기가 용이하고, 같은 API를 요청하는 컴포넌트가 여러 개 있으면 해당 API로의 요청이 단 한 번만 이루어진다.
  2. 반환된 데이터를 전역으로 관리하기 용이
    또한 같은 API로 요청한 컴포넌트들은 반환된 데이터를 서로 공유한다. 내부적으로 어딘가에 응답 데이터를 저장해놓고 공유하는 것으로 보인다

설치

# npm
npm i swr
# yarn
yarn add swr

적용

우선, 데이터를 가져오는 API를 호출하는 함수 fetcher 함수를 생성한다. 이 핵심 함수와 같이 useSWR 훅을 사용하여 데이터를 가져와서 관리할 것 이다.

const fetcher = (url) => fetch(url).then((res) => res.json());

주문내역 데이터를 가져오는 함수를 useSWR 훅을 사용해서 개발한다고 가정하자:

import useSWR from 'swr';

const MyComponent = () => {
  const { data, error } = useSWR('/transaction', fetcher);

  if (error) {
    return <div>Error while fetching data</div>;
  }

  if (!data) {
    return <div>Loading...</div>;
  }

  return <div>Transaction: {data}</div>;
};

데이터가 로딩 중인지, 오류가 발생했는지, 아니면 데이터를 표시할 준비가 되었는지를 확인하고 해당 상태에 따라 적절한 UI를 렌더링 하며 사용하면 된다.

이제 주문 데이터를 가져오고, 데이터의 로딩 상태와 오류 상태를 관리할 수 있다. SWR은 이전에 가져온 데이터를 캐시 하여 재사용하며, 일정한 주기로 데이터를 다시 검증하여 새로운 데이터를 가져온다.

SWR은 오류 처리를 위한 기능도 제공해준다고 한다. 만약 데이터를 가져오는 과정에서 오류가 발생하면, 이전에 캐시 된 데이터를 사용하여 애플리케이션을 계속해서 작동시킬 수 있다고 한다.

옵션

이뿐만 아니라, SWR에서 제공하는 옵션들을 사용하면 더 섬세하게 컨트롤이 가능하다.
예를 들면:

  • revalidateOnReconnect: 네트워크 연결이 복구될 때 데이터를 다시 가져올지 여부를 설정한다.
  • revalidateOnMount: SWR 훅이 마운트 될 때 데이터를 다시 가져올지 여부를 설정한다.
  • revalidateOnFocus: 페이지가 포커스를 얻을 때 데이터를 다시 가져올지 여부를 설정
  • refreshInterval: 데이터를 자동으로 갱신하는 간격을 설정한다.
  • errorRetryCount: 에러 발생 시 자동 재시도를 수행할 최대 횟수를 설정한다.

이 외 옵션들도 많이 있기 때문에 상황에 따라 사용하면 섬세하고 간단하게 데이터를 가져오고 관리할 수 있는 강력한 도구로써 사용할 수 있다.

 

======================================================================

SWR 라이브러리의 몇가지 특성.

const { data, mutate } = useSwr("http://localhost:4000/api", fetcher, {
    // refreshInterval: 1000,
  });
  const [name, setName] = useState("");

  const createItem = async (e) => {
    const curCache = data;
    mutate(
      [
        ...data, //기존데이터
        {
          name, //axios.post로 보내는 name을 보내기 전에 미리 업데이트 하고 있음(새로 추가되는 데이터)
        },
      ],
      false //서버에 다시 요청하여 값을 서버에 반영할 것인지를 묻는 인자. 즉 useSwr을 한번더 실행할지를 묻는 것
    );

    const resp = await axios.post("http://localhost:4000/api", {
      name,
    });

    //post를 보내고 이와같이 한번더 mutate를 사용하여 서버에서 id를 가져오는 즉시 가져온 값을 화면에 랜더링해줌
    // mutate(
    //   [
    //     ...data, //기존데이터
    //     resp.data,
    //   ],
    //   false //서버에 다시 요청하여 다시 값을 가져올지를 묻는 인자. 즉 useSwr을 한번더 실행할지를 묻는 것
    // );

    //경우에 따라서는 위와같이 axios.post를 통해 가져온 값을 저장하지 않는 경우도 있다(위에서는 resp변수에 그값을 가지고 있음). 그럴경우 GET요청을 별도로 한번 보내 데이터를 가져오게 되는데
    //그 역할을 하는 것이 trigger이다. 왜 이름이 trigger야? POST요청을 보내고 자동으로 GET요청을 보낸다고 하여 trigger라고 불림.
    trigger("http://localhost:4000/api");
  };

1. mutate

revallidate와 mutate의 차이점: 간단하게  revalidate는 서버로 요청보내 가져온 데이터로 상태를 갱신하는 것이고 mutate는 서버로 요청을 보내지 않고 프론트에서 먼저 상태를 변경하는 것입니다. 즉 mutate를 사용하면 서버에 요청을 안보낼 수 있는 방법이 생기는 것입니다. 

axios.post로 서버로 데이터를 보내기전에 미리 클라이언트 화면에 업데이트 할수 있다.(더 빠른 사용자 경험 만족시킬 수 있음. 윗글에서 언급된 낙관적인 UI(Positive UI)와 관련되는 것이 이 mutate이다)


2. trigger

POST요청만 하면 따로 GET요청을 보내지 않더라도 GET요청을 자동으로 보내준다.

직접적으로 개발자 도구의 NETWORK의 api전송 내역의 Headers를 보면 아래와 같이 확인할 수 있다.

 

3.  하나의 화면에서 같은 url을 가지는 useSwr을 여러번 사용해도 서버로는 한번의 요청만이 전송됩니다. 그것이 SWR의 장점입니다. 실습코드에서 이를 확인할 수 있음. ReactFront파일의 App.jsx에서 useSwr을 사용하고 Counter.jsx에서 useSwr을 사용하는데도(각각의 url은 서로 같음)서버로의 요청은 한번만 전송되고 처음에 데이터를 가져오고 그것을 저장한 캐쉬에서 데이터를 꺼내서 씀. 즉 SWR은 리소스 사용면에서 효과적입니다.

4. refreshInterval:  설정한 시간을 간격으로 지속적으로 refresh해줌