“SWR”이라는 이름은 HTTP RFC 5861에 의해 알려진 HTTP 캐시 무효 전략인 state-while-revalidate 에서 유래되었다. SWR은 먼저 캐시로부터 데이터를 반환한 후, fetch 요청(재검증)을 하고, 최종적으로 최신화된 데이터를 가져오는 전략이다.
SWR을 사용하면 컴포넌트는 지속적이며 자동으로 데이터 업데이트 스트림을 받게 된다. 그리고 UI는 항상 빠르고 반응적이다.
개요
import useSWR from 'swr'
function Profile() {
const { data, error } = useSWR('/api/user', fetcher);
if (error) return <div>failed to load</div>
if (!data) return <div>loading...</div>
return <div>hello {data.name}!</div>
}
위 예시에서, useSWR hook은 key 문자열과 fetcher 함수를 받는다. key는 데이터의 고유한 식별자이며(일반적으로 API URL) fetcher로 전달될 것이다. fetcher는 데이터를 반환하는 어떠한 비동기 함수도 될 수 있다. 네이티브 fetch 또는 Axios와 같은 도구를 사용할 수 있따.
hook은 두 개의 값을 반환한다 : data, error
기능
단 한 줄의 코드로 프로젝트 내의 데이터 가져오기 로직을 단순화할 수 있으며, 다음과 같은 모든 놀라운 기능들을 바로 사용할 수도 있다.
- 빠르고, 가볍고, 재사용 가능한 데이터 가져오기
- 내장된 캐시 및 요청 중복 제거
- 실시간 경험
- 전송 및 프로토콜에 구애받지 않음
- SSR / ISR / SSG supprot
- TypeScript 준비
- React Native
SWR은 더 나은 경험을 구출할 수 있도록 속도, 정확성, 안정성의 모든 측변을 다룬다.
- 빠른 페이지 네비게이션
- 인터벌 폴링
- 데이터 의존성
- 포커시스 재검증
- 네트워크 회복시 재검증
- 로컬 뮤테이션
- 스마트한 에러 재시도
- 페이지 및 스크롤 위치복구
- React Suspense
성능
SWR은 모든 종류의 웹 앱에서 중요한 기능들을 제공하므로 성능을 가장 중요시 한다.
SWR의 내장 캐싱과 중복제거 기능은 불필요한 네트워크 요청을 생략하지만, useSWR hook자체의 성능은 여전히 중요하다. 복잡한 앱에서는 단일 페이지 렌더링에 useSWR이 수백 번 호출 될 수 있다.
SWR은 앱에서 다음을 보장한다 :
- 불필요한 요청 없음
- 불필요한 리렌더링 없음
- 불필요한 코드 임포트 없음
어떠한 코드 수정도 필요 없다.
중복제거
앱에서 SWR hook을 재사용하는 것은 아주 일반적이다. 아래 예처럼, 앱이 현재 사용자의 아바타를 다섯 번 렌더링 하게 된다면
function useUser () {
return useSWR('/api/user', fetcher)
}
function Avatar () {
const { data, error } = useUser()
if (error) return <Error />
if (!data) return <Spinner />
return <img src={data.avatar_url} />
}
function App () {
return <>
<Avatar />
<Avatar />
<Avatar />
<Avatar />
<Avatar />
</>
}
각각의 <Avatar> 컴포넌트는 내부에 useSWR hook을 갖는다. 이들은 동일한 SWR키를 갖고 있으므로 거의 동시에 렌더링 되며 단 한번의 네트워크 요청만 발생한다.
성능이나 중복된 요청에 대한 걱정 없이 위 예시의 useUser와 같은 데이터 hook을 어디에서든 재사용할 수 있다.
깊은비교
SWR은 기본적으로 데이터 변경을 깊게 비교 한다. data값이 변경되지 않았다면 리렌더링을 트리거 하지 않는다.
의존성 수집
useSWR은 세 개의 스테이트풀 값을 반환한다. data, error, isValidating 각각은 독립적으로 업데이트 된다. 예를들어, 전체 데이터 가져오기 생명 주기에서 이 값들을 출력한다면 뭔가 다음과 같을 것이다.
function App() {
const { data, error, isValidating } = useSWR('/api', fetcher);
console.log(data, error, isValidating);
return null;
}
최악의 경우에는(첫 번째 요청이 실패하고, 재시도가 성공), 네 줄의 로그가 보일 것이다.
// console.log(data, error, isValidating)
undefined undefined true // => 가져오기 시작
undefined Error false // => 가져오기 종료, 에러 발생
undefined Error true // => 재시도 시작
Data undefined false // => 재시도 종료, 데이터 얻음
컴포넌트가 네 번 리렌더링 되었음을 의미한다. data만을 사용하도록 변경한다면 단 두번의 리렌더링이 발생한다.
// console.log(data)
undefined // => 하이드레이션 / 초기 렌더
Data // => 재시도 종료, 데이터 얻음
내부적으로는 완전히 동일한 과정이 발생한다. 첫 번째 요청에서 에러가 발생했고 재시도에서 데이터를 얻었다. 그런데 SWR은 컴포넌트가 사용한 상태만을 업데이트하며, 이제는 data만 그렇다.
이 모든 세가지 상태를 항상 사용하고 있지 않다면, 이 기능의 이점을 누리고 있다. 이 최적화의 결과가 Vercel에서는 ~60% 더 적은 리렌더링의 결과를 얻었다.
왜 쓸까?
SWR은 결국 클라이언트에서 서버에 요청을 해서 data를 가져오는 기능을 편리하게 사용할 수 있도록 도와주는데, next.js와 호환성 뿐만 아니라 브라우저 성능 최적화에 있어서도 큰 장점을 보인다.
'Frontend' 카테고리의 다른 글
| copy-on-write 및 방어적 복사 (0) | 2022.12.18 |
|---|---|
| 프로그래머스 > 예상 대진표 (0) | 2022.10.29 |
| MobX의 철학 (0) | 2022.07.27 |
| 리팩토링 6강 기본 변수, 함수에 대해서 (0) | 2022.07.26 |
| useContext란? (0) | 2022.07.19 |