SWR[stale-while-revalidate]에 대하여

Gee·2022년 5월 1일
2

서론

SWR을 공부하게 된 계기는 작년에 Redux를 사용하여 프로젝트를 진행했다가 길어지는 코드량과 저장하고 있는 데이터를 업데이트 해주기위해서 많은 노력을 하다보니 조금 지쳤던 거 같습니다.
다른 라이브러리를 공부하고 싶었고, 그중에서 같은 상태관리 라이브러리는 아니지만 ContextAPI를 살짝 공부하였습니다. 충분히 작은 사이드 프로젝트에서는 활용이 가능하였습니다. 적절하게 분배도 한다면..? 이번에는 제로초 강의를 듣고 SWR 상태관리에 대해서 공부하고 있습니다.
SWR를 공부하면 React-Query는 덤이라고 해서! SWR 공부하고 나중에 React-Query도 사용하면서 장단점을 찾아보고싶습니다.

위에서 말했듯이 Redux를 사용하면서 부딪히게 되었던 문제들이 몇가지 있었습니다. 간략하게 3가지로 정리하자면 아래와 같습니다.

  1. 상태와 변이방법을 정의하기 위한 리듀서와 액션의 코딩량이 많다.
  2. 관리하고 있는 데이터 업데이트를 위해서는 효과적으로 상태 초기화를 하기 위한 고민이 많이 필요하다.
  3. 수시로 업데이트 해주기위해서는 로컬 스토어 상태를 원격 서버 상태와 동기화해야하는 추가 작업이 필요하다.

3가지 문제를 각각 해야할 수 있는 다른 방안들이 존재하겠지만 3가지 모두를 해결할 수 있는 방법은 SWR과 요즘 뜨고 있는 React-Query 인 거 같습니다.
그 중에서 SWR에 대해서 소개할 예정입니다.

SWR이 무엇인가요 ?

SWR은 Nextjs로 유명한 vercel에서 만든 것으로 먼저 캐시(stale)로부터 데이터를 반환한 후, fetch 요청(revalidate)을 하고, 최종적으로 최신화된 데이터를 가져오는 전략입니다.

import useSWR from 'swr'

function Point(){
	const {data, error} = useSWR('/api/user/', url => {
    	return fetch(url).then(res =>. res.json())
    })
    if (error) {
    	return <div> failed to load </div>
    }
    if (!data) {
    	return <div> Loading...</div>
    }
  return <div> {data} </div>
}

SWR 기본 코드입니다.
주목해야 할 부분은 useSWR은 한번 fetch한 원격상태의 데이터를 내부적으로 캐시하고 다른 컴포넌트에서 동일한 상태를 사용하고자 할 경우 이전에 캐시했던 상태를 그대로 리턴해줍니다.
여러 컴포넌트들에서 모두 동일하게 원격의 상태를 공유할 수 있습니다. 이부분은 기존 라이브러리들의 역할과 동일합니다. 하지만, SWR은 추가적인 기능들로 더욱 편리하게 기존 라이브러리들을 대체할 수 있을 것이라고 기대할 수 있습니다.

프론트엔드 개발자의 작업 중 하나는 데이터를 적절하게 뿌려주는 역할이겠지요. 이러한 역할을 수행하기 위해서는 적절한 시점에 원격 서버의 데이터를 들고와 로컬 스토어 상태를 초기화하고 사용자 액션을 받아서 원격상태에서 데이터를 추가하거나 수정, 삭제를 하게됩니다.
이때 원격상태가 변경될 때마다 그에 맞게 로컬 스토어 상태도 동기화 시키는 작업은 필수이겠지요..

Redux를 사용했을 때, 동기화시키는 것에 조금 현기증이 나긴했습니다..ㅎㅎ
이때 이러한 현기증을 해결해주는 SWR의 기능은 아래와 같습니다.

SWR은 원격상태와 로컬상태를 하나로 통합합니다.

SWR은 해당 데이터를 마치 원격상태와 연결된 데이터 스트림으로서 바라볼 수 있도록 데이터 fetching 단계를 추상화합니다. 연결도 안되어있는데 이게 가능하다고..? 생각하실 것입니다.

SWR은 내부적으로 적절한 타이밍에 지속적으로 데이터를 업데이트해줍니다. 실시간은 아닐 수 있겠지만, 적절한 타이밍에 데이터를 폴링하기 때문에 최신상태를 유지할 수 있습니다.
또한 브라우저창이 focus를 얻을 때 또는 네트워크 on/off 상태를 감지하여 자동으로 데이터를 fetch합니다. 주기는 설정이 가능합니다. (option 기능으로)

SWR로 상태관리가 가능할까요?

사실상, SWR은 상태관리용 라이브러리가 아니라 데이터 가져오기용 라이브러리이다. 하지만, useSWR을 모듈화하고 독립된 함수로 처리한다면, 여러 컴포넌트들에서 필요한 상태를 가져와 사용할 수 있으며 이러한 컴포넌트간 전역상태를 공유할 수 있다는 특성때문에 기존 상태관리 라이브러리를 대체할 수 있습니다.

setState와 같이 변경된 데이터를 업데이트하기 위해서는, mutate함수를 이용하면 된다. (revalidate => mutate로 통합됨.) mutate함수가 호출되면 해당 상태를 즉시 fetch하고 데이터를 갱신하게 됩니다.

mutate함수를 사용할 때 데이터 fetch 없이 로컬에 캐시되어있는 상태만 제어하기 위해서는 mutate(user, false)해주시면 됩니다. (두번째 인자에 false 넣어주시면 됩니다. )

  • 로컬상태 관리만 하는 것도 가능합니다. 필요에 따라 window, sessionStorage, localStorage, 클로저 변수 등을 적절하게 사용하여 구현하면 됩니다.

SWR API Options

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

1. Parameter

  • key : 요청을 위한 고유한 키 문자열 또는 함수, 배열, null 값 (조건부 요청 가능)
  • fetcher: (옵션) 데이터를 가져오기 위한 함수를 반환하는 Promise
  • options : SWR hook을 위한 옵션 객체

2. return value

  • data: fetcher가 이행한 주어진 키에 대한 데이터(로드되지 않았다면 undefined)
  • error: fetcher가 던진 에러(또는 undefined)
  • isValidating: 요청이나 갱신 로딩의 여부
  • mutate(data?, shouldRevalidate?): 캐시 된 데이터를 뮤테이트하기 위한 함수

3. options

너무 많아서, 아래의 페이지에서 확인하시면 됩니다.
https://swr.bootcss.com/docs/options

결론

모든 경우를 기존 라이브러리에서 SWR로 대체할수는 없겠지만, Redux가 갖고 있던 단점들은 어느정도 대체할 수 있을것이라고 생각합니다.
이번에 사이드 프로젝트를 할 예정인데, 적극적으로 SWR를 사용하여 프로젝트를 완성시켜볼 예정입니다! 화이팅 :)

덤으로, 공식적인 SWR-dev tools는 없는 거 같아서 죠르디님께서 만들어주신 devtools를 들고 왔습니다. 같이 사용하면 좋을 거 같습니다 :0
https://www.npmjs.com/package/@jjordy/swr-devtools

추가적으로 프로젝트하면서 느낀 점들

사이드 프로젝트 진행하면서 SWR이 편리한 것은 온몸으로 느꼈다. 하지만, 뭔가.. 뭔가 이상한 느낌이 들었다. ComponentA, B 에서 동일한 api를 호출한다는게 code상으로도 별로고 성능적으로도 별로인거 같았다. 개념을 조금 더 파고 들자해서 비슷한 라이브러리인 React query 영상을 보고 Server State, Client State 개념이 나뉜다는 것을 알게 되었다. (멍퉁이..)

Redux 는 상태 관리 라이브러리로써, Client State, Server State 모두 관여할 수 있다.
하지만 SWR 은 data fetching 라이브러리로써 Client State 관점과는 다른 이야기이다. (두둥!!)

작은 사이드 프로젝트라서 client state 쪽은 context api를 도입해서 사용중이다.

참고 자료 : https://youthfulhps.dev/web/stale-while-ravalidate/#stale-while-revalidate

profile
작은 실패, 빠른 피드백, 다시 시도

0개의 댓글