데이터 패칭 라이브러리 - SWR (3. 특징과 응용)

eeensu·2023년 7월 31일
post-thumbnail

SWR 사용 효과는?

  • 효율적인 리렌더
    이러한 데이터 패칭 라이브러리를 사용하지 않고 useEffect() 로 단순하게 axiosfetch를 이용하면, 자식에게 정보를 전달하기 위해서 이러한 로직을 최상단 컴포넌트 에서 진행해야한다. 그리고 필요한 모든 자식에게 정보를 전달하기 위해 props로 넘겨줘야 한다. 하지만 이는 props drilling을 유발할 수 있으며 유지보수가 어려워질 수 있다. react에서 제공하는 ContextAPI를 이용하여 props drilling을 피할 수 있지만 비효율적인 re-render가 발생할 수 있다. swr과 react-query는 이러한 문제를 간단하게 해결해준다. 필요하면 어디서든 꺼내서 쓰고, 데이터가 없으면 fetching해서 쓰고, 데이터가 기존에 있으면 caching된 것을 쓰면 된다.
  • 독립적인 컴포넌트로 세분화 가능
    useSWR을 사용하면 데이터는 데이터가 필요한 컴포넌트에 범위가 제한되어 있고, 서로에게 독립적이다. 부모 컴포넌트는 데이터나 데이터 전달에 대한 정보를 알 필요가 없고, 단지 자식들을 render하면 될 뿐이다. 이 덕분에 최대한 컴포넌트를 세분화할 수 있고, 이는 react의 컴포넌트 재사용성을 증가시켜주는 효과로 다가온다.
  • 실시간 데이터 제공 가능
    또한 애플리케이션은 이제 사용자 포커스나 네트워크 재연결 시에 데이터를 갱신할 수 있다. 이는 사용자의 노트북이 슬립으로부터 깨어나거나 탭을 전활할 때 자동으로 데이터가 다시 갱신된다는 것이다. 이는 user에게 유의미하고 실시간적인 데이터를 제공하기 위한 목적이다.
  • custom한 옵션 정의
    데이터를 자동으로 다시 패칭하는 refresh 옵션은 개발자가 임의로 지정할 수 있다. useSWR의 세번째 인자로
    { refreshInterval: 1000 } (1초) 를 주면 된다. 그러나 개발자가 이러한 자동 갱신 기능을 필요로 하지 않으면 이 역시 option으로 주거나, 혹은 useSWRImmutable() 을 사용한다. 그리고 이러한 option을 전역적으로 설정하여 사용하고 싶으면 useSWRConfig() 사용할 수 있다.

즉 주요 기능을 정리하면, SWR은 데이터를 가져오는 것을 목적으로하는 데이터 패칭기능이고, 그 전에 cache된 데이터가 있으면 그것을 share하고, 그 기준은 key값이다.



옵션의 종류

  • errorRetryInterval
    error가 발생하면, swr은 자동으로 error 재시도를 적용한다. 이 로직은 지수 백오프 알고리즘을 적용하기에, 에러 재시도 속도는 갈수록 느려진다. 계속 재시도하면 리소스가 낭비될 수 있기 때문이다. 이러한 기능도 onErrorRetry 옵션을 통해 오버라이드할 수 있다. 또한 error 재시도 기능을 사용하지 않으려면 shouldRetryOnError 옵션을 false로 설정하면 된다.

  • errorRetryCount
    최대 에러 재시도 수를 정할 수 있다.

  • onSuccess
    데이터 패칭이 성공하고 종료되었을 경우의 호출되는 콜백 함수이다.

이러한 custom 옵션에는 매우 다양한 종류들이 더 있다. 공식문서에서 찾아볼 수 있다.




응용

조건부 호출

또한 useSWR은 알아서 요청하는 hook이기에 개발자가 관장하기 쉽지 않다. 개발자가 이 hook이 언제 요청되는지 인지하기 힘들다. 또한, 개발 도중 useSWR 훅이 자동으로 알아서 호출되어야 하는 것이 아닌 특정 시점에 정확히 호출되어야 하는 상황이 생기면, 이를 조건부로 hook을 호출할 수 있다.

 // 방법1
 const { data: user1 } = useSWR(userData ? '/api/user/id' : null, fetcher);

 // 방법2                               
 const { data: user2 } = useSWR(() => userData ? '/api/user/id' : null, fetcher);	

 // 함수로 전달할 때, swr은 함수의 return값을 key로 사용한다



의존성 호출

useSWR사이에서 data끼리 의존하는 것 또한 가능하다.

function MyProjects () {
  const { data: user } = useSWR('/api/user', fetcher1);
  const { data: projects } = useSWR(() => `/api/projects?uid=${user.id}`, fetcher2);
  /* 함수를 전달할 때, SWR은 반환 값을 `key`로 사용한다.
   첫번 째 swr이 falsy를 던지거나 반환한다면, 두번 째 SWR은 일부 의존성이 준비되지 않은 것을 알게 된다. 
   이 예시의 경우 `user.id`는 `user`가 로드되지 않았을 때, 로딩 혹은 에러를 던진다.*/
 
  if (!projects) return 'loading...'
  
  return 'You have ' + projects.length + ' projects'
}



key 값의 다양한 형태

어떤 상황에서는 fetcher함수에 여러 인자를 사용해야하는 다중 인자 상황이 올 수 있다. 예를 들어 다음과 같은 hook은 올바르지 않다.

useSWR('/api/user', url => fetchWithToken(url, token));

데이터의 식별자로서 키는 '/api/user' 이고, 이는 이후 어떤 token이 적용되는 key값은 유일하기에 swr은 이를 다른 데이터로 인식하지 못한다.

이럴 경우에는, key 값을 배열로 주입한다.

useSWR(['/api/user', token], url=> fetchWithToken(url, token));

이렇게 하면 token의 값에 따라 다른 key로 인식되어 올바르게 로직이 작동한다.

또한 이전 버전에서는 key값으로 객체를 전달할 수 없었지만, 이제는 바로 전달할 수 있으며 fetcher가 그 객체를 받는다.

const { data: orders } = useSWR({ url: '/api/orders', args: user }, fetcher);
profile
안녕하세요! 프론트엔드 개발자입니다! (2024/03 ~)

0개의 댓글