(React) SWR

Mirrer·2022년 10월 8일
0

Library

목록 보기
14/17
post-thumbnail

SWR

원격데이터 fetch를 위한 커스텀 훅

SWR(stale-while-revalidate)클라이언트 서버에서 data를 가져오는 기능(fetching)을 편리하게 사용할 수 있도록 도와주는 hook이다.

SWR은 먼저 캐시로부터 데이터를 반환한 후, fetch 요청(재검증)을 하고, 최종적으로 최신화된 데이터를 가져온다.

그래서 컴포넌트는 지속적이며 자동으로 데이터 업데이트 스트림을 받을 수 있다.


SWR의 장점

SWR의 대표적인 장점은 다음과 같다.

  • 자동화가 간단하다.

  • 가볍고 빠르기 때문에 데이터의 업데이트 또한 빠르게 이루어져 reactive한 환경을 갖출 수 있다.

  • SSR(Server-Side-Rendering), SSG(Static-Site-Generation), ISR(Incremental-Static-Generation) 환경에서 모두 사용할 수 있다.

  • vercel에서 개발하여 Next.js와 호환성능이 좋다.

  • 같은 역활의 상태관리 라이브러리인 ReduxReducer, Saga보다 간결하게 구현할 수 있어 코드의 양이 줄어든다.

SWR은 클라이언트 서버에서만 사용할 수 있어 POST, PATCH, DELETE...등 데이터베이스의 데이터를 바꿔야할 경우에는 적합하지 않다.

그래서 Load와 같은 비동기 Action 또는 Get요청을 처리하기 적합하다.


SWR 설치 및 사용

SWR 설치

아래 npm명령어를 통해 SWR을 설치한다.

npm i swr

SWR 사용방법

SWRuseSWR(Key, Fetcher)의 형태로 사용하며, Fetcher 함수를 이용하여 Key 주소에서 가져오는 데이터를 전역적으로 관리한다.

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

이외에 사용되는 파라미터, 반환값의 종류는 다음과 같다.

  • Parameter

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

  • Return

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


SWR 예제

import useSWR from 'swr'; //swr 불러오기

const fetcher = (url) => axios.get(url, { withCredentials: true }).then((result) => result.data);

const { data, error } = useSWR('/post', fetcher);

첫번째 인자는 두번째 fetch 함수의 첫번째 인자(url)로 전달된다.

이 후 fetch 함수가 데이터를 로드하면 해당 응답이 data로, 오류가 발생하면 해당 오류가 error에 세팅된다.

컴포넌트에서는 dataerror 상태에 따라 알맞게 결과를 렌더링 해주면 된다.

import useSWR from 'swr';

// fetcher는 첫번째 인자로 입력한 주소를 어떻게 실제로 가져올지를 작성
const fetcher = (url) => axios.get(url, { withCredentials: true }).then((result) => result.data);

// fetcher의 결과는 data, error는 error
// data, error 둘다 없다는 것은 아직 서버 요청중
const { data, error } = useSWR('/post', fetcher);

// 에러 발생
if (error) {
  console.error(error);
  return <div>에러가 발생합니다.</div>; 
}

const Post = () => {
  return (
    <div>`포스트 정보: ${data}`</div>		
  )
};

SWR의 상태값 공유

아래 예제의 SWR같은 url 주소를 사용하기 때문에, 동일한 캐시값을 받아 이를 통해 같은 상태값을 공유한다.

// FirstPost.js
import useSWR from 'swr'

export default () => {
  const { data, error } = useSWR('/post', url => axios.get(url, { withCredentials: true }).then((result) => result.data);
}
// SecondPost.js
import useSWR from 'swr'

export default () => {
  const { data, error } = useSWR('/post', url => axios.get(url, { withCredentials: true }).then((result) => result.data);
}

SWR의 데이터 캐싱

위에서 설명했듯 기본적으로 SWR은 데이터를 가져오기 위한 React Hooks이다.

최초 Fetcher함수가 실행되면, 원격상태의 데이터를 내부적으로 캐시 즉, 클라이언트에 잠시 저장한다.

이 후 다른 컴포넌트에서 동일한 상태를 사용하게 되면 캐시했던 상태를 그대로 return한다.

그래서 원격 데이터를 사용하는 서로 다른 컴포넌트가 같은 key를 사용한다면 동일한 상태를 공유할 수 있다.


캐싱 간격

SWR의 캐싱 간격은 위에서 설명한 Parameter 옵션, Mutate 함수를 통해 설정할 수 있다.

만약 지정하지 않는다면, 컴포넌트 렌더링에 따라 원격 데이터를 요청받는다.

Parameter 옵션 (revalidateOnFocus)

SWR의 세번째 ParameterrevalidateOnFocus 옵션을 지정하면, 창이 포커싱 됬을 때 자동으로 데이터가 갱신된다.

이외에 사용할 수 있는 Option Parameter의 종류는 해당 홈페이지에서 확인 할 수 있다.

const {data, error} = useSWR('/post', fetcher, {
  revalidateOnFocus: true,
});

Mutate 함수

Parameter 옵션이외에 Mutate 함수를 사용해도 데이터를 갱신할 수 있다.

Mutate함수는 Promise이며, 호출시 해당 상태를 즉시 Get하여 데이터를 갱신한다.

사용방법은 다음과 같다.

// index.tsx
const {data, error} = useSWR('/post', fetcher);

const handleChange = async (post) => {
  await updatePost(post)
  return mutate()
}

또한 첫번째 인자에 갱신할 데이터를 직접 지정할 수 있으며, 두번째 인자로 데이터 Fetch여부도 지정할 수 있다.

const handleChange = async (post) => {
  await updateUser(post)
  mutate(post, false)
}

SWR ServerSideRendering

SWRServerSideRendering방법은 다음과 같다.


  1. getServerSideProps에서 서버에서 받은 데이터를 return
export const getServerSideProps = wrapper.getServerSideProps(async (context) => {
  const cookie = context.req ? context.req.headers.cookie : '';
  axios.defaults.headers.Cookie = '';
  if (context.req && cookie) {
    axios.defaults.headers.Cookie = cookie;
  }
  
  context.store.dispatch({
    type: LOAD_POST_REQUEST,
  });
 
  context.store.dispatch(END);
  await context.store.sagaTask.toPromise();
  return { props: { data: 123 } } // 서버에서 받은 데이터를 전달
});
  1. 전달받은 데이터를 컴포넌트의 props로 접근
const Post = ({ data }) => { // 전달받은 데이터 
	const { data, error } = useSWR('/post', fetcher); 
	return (
				:
				:
	)
};
  1. 전달받은 propsSWR세번째 인자({ initialData })로 추가한다.
const fetcher = (url) => axios.get(url).then((result) => result.data);

const Post = ({ data }) => { 
	const { data, error } = useSWR('/post', fetcher, { data }); 
	return (
				:
				:
	)
};

참고 자료

Usage with Next.js - SWR
웹 게임을 만들며 배우는 React - 제로초

profile
memories Of A front-end web developer

0개의 댓글