[react] SWR을 쓰는 이유

minky·2022년 6월 26일
0
post-thumbnail

최근들어 이직 고민이 많아 기술면접을 볼 일이 종종 있었다. 불합격이든 거절이든 최종적으로 옮기지는 않았지만 면접을 보면서 한가지 꺠달은 것이 있었다.

나는 해당 기술을 왜 쓰는가? 라는 고민을 너무 안하고 살았다. 라이브러리를 도입할 때 비슷한 종류끼리 비교하고 선택한 후 금방 까먹는 식이 반복되니 대답이 추상적으로 변할 수 밖에 없다고 느꼈다. 그래서 현재 쓰고 있는 라이브러리, 프레임워크, 언어 등에 관해서 쓰고 싶은 주제를 위주로 정리하고자 한다. 첫번째는 swr 이다.

목차

  1. SSR, CSR, SWR
  2. react-query vs SWR
  3. 마무리
  4. 참고자료

1. SSR, CSR, SWR

interaction이 필요한 웹페이지를 만든다는 것은 크게 두가지를 고민하는 과정이라고 생각한다. 첫번째는 어떻게 데이터를 가져와서 보여줄 것인가, 두번째는 어떻게 데이터를 업데이트하고 보여줄 것인가 이다. 해당 과정을 유저가 특별히 의식하지 않고 물흐르는듯이 진행되어 자연스러운 사용자경험을 추구하는 것이 프론트 개발자의 일이다.

react를 쓴다고 했을 때 next, remix 등의 사용이 일반적인 지금 시점에서 SSR, CSR은 우열의 문제가 아니라 상황에 따른 선택이다. 그 중 초기 데이터 페칭에 중점을 둔 기술이 SSR(ServerSide Rendering)이고 데이터 업데이트에 보다 초점을 맞춘 기술이 CSR(ClientSide Rendering)이라고 생각한다. SWR(Stale While Revalidate)은 CSR 측면에서 데이터 fetching 로직을 단순화하면서 다양한 옵션을 통해 보다 강력하게 만들어주는 라이브러리이다.

SWR을 정리하기 위한 글이니 SSR과 CSR에 관한 설명보단 SWR이 필요한 이유에 관해 이야기해보자. swr 한국어 공식 홈페이지에는 swr에 관해 이렇게 설명한다.

"SWR"이라는 이름은 HTTP RFC 5861에 의해 알려진 HTTP 캐시 무효 전략인 stale-while-revalidate에서 유래되었습니다. SWR은 먼저 캐시(스태일)로부터 데이터를 반환한 후, fetch 요청(재검증)을 하고, 최종적으로 최신화된 데이터를 가져오는 전략입니다.
출처ㅣ https://swr.vercel.app/ko

swr은 api 주소와 fetch함수를 파라미터로 받아 데이터를 캐싱하고 이를 설정한 옵션, 혹은 mutate 설정에 맞게 재검증하여 클라이언트 데이터를 서버와 동기화시켜주는 역할을 한다.

이런 생각이 들 수 있다. getServersideProps로 inital Data를 가져오고 이를 recoil, redux 등의 global state로 관리하면서 update 할 때만 POST와 상태관리를 동시에 진행하면 되는 것이 아닌가? 사실 내가 했던 생각이다. 이를 notification을 불러오는 사례로 swr을 사용하는 경우와 useEffect로 fetch하는 경우로 비교해보자.

import useSWR from 'swr'

interface Notification {
	content: string
    createdAt: number
}

function Alarm() {
// swr을 사용하는 경우
const { data, mutate, error } = useSWR<{ notifications: Notification[] }>	(
    'api/notifications',
    fetcher,
  )
  
 // swr을 사용하지 않는 경우
 const [notifications, setNotifications] = useState<Notification[]>()
  const [notificationsError, setNotificationsError] = useState<Error>()

  useEffect(() => {
    const _loadNotifications = async () => {
      try {
        const rawResponse = await fetch('api/notifications', { method: 'GET' })
        const response = (await rawResponse.json()) as Notification[]
        setNotifications(response)
      } catch (err) {
        setNotificationsError(err as Error)
      }
    }

    _loadNotifications()
  }, [])

return (
    <ErrorBoundary error={error}> // 또는 notificationsError
      <LoadingBoundary loading={!data}> // 또는 !notifications
        <AlarmList notifications={data.notifications} /> // 또는 notifications
      </LoadingBoundary>
    </ErrorBoundary>
  )
}

코드도 훨씬 간결해질 뿐더러 mutate 함수를 통한 revalidate도 보다 쉽고 강력해진다.

2. react-query vs SWR

react-query 와 SWR 모두 위에서 설명한 것과 같이 client side에서 data fetching 시 caching, 서버와의 동기화, pre-fetch 등의 여러 옵션을 활용한 최신 데이터 관리를 위해 나온 라이브러리이다. 그렇다면 두 라이브러리는 어떤 차이가 있을까?

사실 react-query 와 SWR 중 무엇을 쓸지는 그저 선택의 문제라고만 생각했는데, 이번에 알아본 결과 다소 성격이 다름을 알 수 있었다. 우선 2022년 6월 29일 기준 npm weekly download 수는 react-query가 140만, swr이 76만으로 두 배 가까이 차이가 난다. 그러나 이것이 react-query가 swr보다 좋다는 것을 의미하지는 않는다. Caching clash: useSWR() vs. react-query 글에서 언급한 차이점을 짚어보면

1) global fetcher의 유무

SWR은 SWRConfig 라는 global로 fetcher함수나 세부 option들을 지정할 수 있는 configuration provider를 제공한다. react-query역시 provider가 필요하지만 react-query는 react app 전체에서 해당 라이브러리의 훅을 사용하기 위해 컨텍스트의 provider를 선언하듯이 필요하고, swr은 정말 간편한 config를 위한 provider를 제공한다.

import { SWRConfig } from 'swr'

return (
	// 이런 식으로 fetcher함수와 원하는 옵션 플래그를 줄 수 있다.
	<SWRConfig
      value={{
        fetcher: customFetcher,
        revalidateIfStale: true,
        revalidateOnFocus: false,
        shouldRetryOnError: false,
      }}
    >
     {children}
    </SWRConfig>
)

2) Garbage collection의 유무

react-query의 경우 안쓰는 쿼리 데이터나 stale들을 검사해 (아무런 설정이 없을시 5분) 자동으로 이를 관리해준다. swr은 따로 이를 관리해주지 않는다.

3) Request cancellation

이 역시 react-query가 장점을 가지는 측면인데 요청이 반응이 없거나 만료되었을 경우 쿼리를 수동, 또는 자동으로 취소해주는 기능이 있다. swr은 딱히 이런 기능은 없지만 AbortController API를 활용해 직접 적용할 수는 있다.

function useCancelableSWR (key, opts) {
  const controller = new AbortController()
  return [useSWR(key, url => fetch(url, { signal: controller.signal }), opts), controller]
}

// to use it:
const [{ data }, controller] = useCancelableSWR('/api')

// ...
controller.abort()

출처: Caching clash: useSWR() vs. react-query

둘 모두 강력한 remote fetch library 이지만 graphQL과 전반적인 속도 때문에 scalable이 필요하거나 대용량 서비스에는 useSWR이 적합하며, 사이드 프로젝트나 작은 앱에는 react-query가 권장된다고 해당 글은 설명한다. restAPI를 사용하고 아직 회사의 제품 사용자가 많지 않은 입장으로서 해당 이점에 관해 체감하지는 못한다. graphQL을 제대로 사용해봐야 알 것 같다.

3. 마무리

사실 swr과 suspense에 관한 글도 쓰고 싶었는데, 이는 react18에 관해 쓸 때 복습 겸 다루기로 하고 이만 쓰고자 한다. 더 많은 코드와 예제가 있으면 좋았겠지만 또 이 글 역시 언제까지고 재고로 묵혀둘 수가 없어 일단 창고 개방을 하고자 한다.. 만족스럽지는 않지만 어떻게든 마무리 지으려고 노력하면서 swr에 관해 더 깊이 생각하고 공부할 수 있는 기회가 되었다. 수정 및 보완에 관한 다짐을 하면서, 끝!

4. 참고자료

  1. swr 한국어 홈페이지 - https://swr.vercel.app/ko
  2. react-query 공식문서
  3. Caching clash: useSWR() vs. react-query
  4. REACT QUERY VS SWR
profile
프로덕트가 발전하는 과정을 즐기는 개발자입니다.

0개의 댓글