goongoguma's blog

React Query vs SWR

대부분의 최신 웹 어플리케이션들은 외부 데이터 소스에 의존합니다. 그리고 리액트에서, 원격의 엔드포인트에서 fetch 혹은 axios를 사용해 데이터를 가져옵니다.

그러나, 이 두개의 라이브러리들은 딱 그런 일만을 할 뿐입니다. 로딩의 상태, 에러 핸들링, 캐싱, 페이지네이션 그리고 재검증(re-validation)과 같은 기능들은 따로 만들어야합니다.

하지만 이런 문제를 해결한 두가지 유명한 라이브러리가 있습니다. 이것들은:

React Query

문서에 따르면 이 라이브러리는 다음과 같은 기능들을 제공합니다.

"전역 상태"를 건드릴 일 없이 리액트와 리액트 네이티브 어플리케이션의 데이터를 패치(fetch), 캐시(cache) 그리고 업데이트합니다.

또 다른 라이브러리는

SWR

이 라이브러리는 다음과 같이 자신을 소개합니다.

데이터 패칭(fetching)을 위한 리액트 훅

이 두개의 라이브러리를 비교해보고 어떤 상황에서 어떤 라이브러리의 사용이 더 나은 선택일지 알아보겠습니다.

The common things

첫번째로 이 라이브러리들의 공통점에 관해 이야기해보겠습니다. 라이브러리들은 다음과 같은 일을 공통적으로 수행합니다.

  • Query
  • Caching
  • Polling
  • Parallel Queries
  • Initial Data
  • Window focus re-fetching
  • Network status re-fetching

이제 차이점을 알아보도록 하겠습니다.

Dev tools

이것이 큰 차이점입니다. React query는 Devtool을 제공합니다. 단지 이 Devtool을 root안에 전달해주기만 하면 됩니다.

import { ReactQueryDevtools } from 'react-query/devtools'
 
 function App() {
   return (
     <QueryClientProvider client={queryClient}>
       {/* The rest of your application */}
       <ReactQueryDevtools initialIsOpen={false} />
     </QueryClientProvider>
   )
 }

불행하게도, SWR은 이런 종류의 dev tool을 가지고 있지 않습니다. 써드 파티 패키지를 사용해서 할 수 있기는 합니다.

그래서 이 부분은 react-query의 완승이네요.

Global Error Handler

SWR에서는 전역 에러 핸들링을 SWRConfig의 도움으로 설정할 수 있습니다.

전역 에러 핸들링을 세팅해주기 위해서 root를 아래와 같이 감싸면 됩니다.

global error handling

그런데 이상한점은 React query에서는 이런 기능이 없다는겁니다. 특별한 훅을 직접 만들어서 이런 기능을 추가할 수는 있지만 공식적으로 지원해줬으면 더 좋았을것 같습니다.

update

보아하니, react-query에도 전역 에러 핸들링 기능을 지원해주네요. 전역 설정에서 query cache의 onError를 사용해야 합니다. 아래와 같이요.

const queryClient = new QueryClient({
  queryCache: new QueryCache({
    onError: (error, query) => {
     console.log(`Something went wrong: ${error.message}`)
    },
  }),
})

그래서 이번 라운드는 비긴것 같습니다 :P

Dominik Dorfmeister님 정정해주셔서 감사합니다. 해당 토픽에 관한 이 분의 글은 여기서 확인할 수 있습니다.

Mutation Hooks

React query에서는 mutation 훅은 기본으로 지원합니다. 아래와 같이 사용할 수 있습니다.

const mutation = useMutation(newTodo => axios.post('/todos', newTodo))

하지만 SWR에서는 mutation 훅을 지원하지 않는 대신에 데이터를 수동으로 조작할 수 있는 옵션이 있습니다. 그런데 mutation 훅보다는 편리하지 않습니다.

import useSWR, { useSWRConfig } from 'swr'

function App () {
  const { mutate } = useSWRConfig()
  
  const onClickHandler = () => {
     logout()
     mutate('/api/user')  // invalidate the user data
  }

  return <button> Logout </button>
}

그래서 이번에는 React Query의 완승입니다.

Bundle Size

BundlePhobia에 따르면 SWR의 번들 사이즈는 15kb지만 React Query의 번들 사이즈는 50kb라고 합니다. SWR 사이즈의 3배가 넘네요!

SWR vs React Query

그래서 여러분이 사이즈를 고려한다면 SWR이 여기서 큰 차이로 이깁니다!

Garbage Collection

react-query 문서에 따르면, 쿼리가 5분동안 비활성 상태라면 캐시가 되어진 모든 데이터들은 쓰레기 수집(garbage collected)됩니다.

또한, 이 쓰레기 수집 시간을 cacheTime을 사용해 설정할 수도 있습니다.

하지만 SWR에서는 쓰레기 수집 기능이 존재하지 않습니다. 그래서 필요하다면 캐시를 직접 조작해야하죠.

그래서 React Query의 승리입니다.

Final Verdict

제 생각에는, 두개의 라이브러리 모두 훌륭하고 어플리케이션의 성능을 향상시킴으로써 개발자들의 일을 수월하게 만들어줍니다.

하지만 react-query는 SWR에 없는 강력한 기능들을 가지고 있습니다. 하지만 이러한 기능들은 번들 크기의 증가도 가져왔죠.

그래서 만약 여러분이 간단한 어플리케이션을 만들고 즉시 사용이 가능한 간단한 솔루션을 원한다면 SWR을 선택하는 것이 좋습니다.

하지만 더욱 많은 컨트롤과 커스터마이징이 필요하고 개발자 도구를 최대한으로 사용하고 싶다면 react-query를 사용하는것이 좋죠.

오늘은 여기까지입니다. 비교를 통해 이 두개의 라이브러리들을 더욱 잘 이해하셨으면 합니다.

좋은하루 보내세요!

원문: React Query vs SWR by Mohammad Faisal