SWR로 서버 데이터 가져오기
SWR data fetching
dukjjang •
2023년 1월 23일
dev
우선 데이터를 관리하기 위해 필요한 코드의 양이 많아진다.( 스토어 만들고, 데이터를 가져오고, 스토어에 넣는 액션을 하나하나 지정 등등..) 또한 동적인 요소가 많아지다보면 이것저것 신경써야 할 것이 한두가지가 아니였다.
그러던 중 next js 공식문서를 보다가 SWR을 알게되었다. SWR은 Vercel에서 만든 서버 데이터를 가져오고 캐시를 관리해주는 라이브러리이다. 요즘 많이들 사용하는 react query와 매우 비슷하다.
SWR은 그럼 어떤 문제를 해결하기 위해 생겨났나?
SWR은 "서버상태를 관리하려고 하지말고 그냥 필요한 컴포넌트에서 SWR로 데이터를 요청해서 써" 라고 말한다. 그렇다 생각해보면 필요한 컴포넌트에서 데이터를 가져와 쓰면 굉장히 직관적이고 유지보수도 쉽고 간편하다. 상위컴포넌트에서 밑으로 사용해야하는 컴포넌트까지 내려줄 필요도 없고, 전역으로 서버상태를 전부 관리할 필요도 없이 말이다.
하지만 한가지 의문점이 들었다.
"그러면 서버의 데이터 요청을 너무 많이 하게 되거나, 불필요한 리소스를 많이 잡아먹게 되는건 아닐까? " 하는 생각이였다.
SWR은 이에대해 다음과 같이 얘기한다.
"데이터는 이제 데이터가 필요한 컴포넌트로 범위가 제한되었으며 모든 컴포넌트는 서로에게 독립적입니다. 모든 부모 컴포넌트들은 데이터나 데이터 전달에 관련된 것들을 알 필요가 없습니다. 그냥 렌더링할 뿐입니다. 코드는 이제 유지하기에 더 간단하고 쉽습니다.
가장 아름다운 것은 이들이 동일한 SWR 키를 사용하며 그 요청이 자동으로 중복 제거,캐시,공유되므로, 단한 번의 요청만 API로 전송된다는 것입니다."
- SWR 공식문서 중 -
중복 요청이 되지도 않고 자동으로 캐시관리까지 해준다고 하니 나는 몹시 굉장히 궁금해졌다.
swr을 사용하여 어떻게 데이터를 가져오고 사용하는지 한번 알아보자.
1. 설치
yarn add swrnpm install swr
설치한다음 상단에 import 하여 사용하면 된다.
import useSWR from "swr"
2. useSWR
먼저 SWR로 서버 데이터를 가져오기 위해서는 2가지의 인자를 넘겨줘야 한다. (3번째는 option이다)
const { data, error } = useSWR(key, fetcher)
첫번째 인자인 key에는 서버 데이터요청의 엔드포인트(key)가 들어가게된다.
두번째 인자인 fetcher는 우리가 일반적으로 서버로부터 데이터를 가져오는 fetch 함수이다.
(직접 두번째인자에 작성해도 되고 따로 밑에처럼 만들어서 넣어줄 수 있다. )
const fetcher = (path:string) => fetch(`http://localhost:8080${path}`).then((res)=> res.json())
fetcher 함수
중요한것은 이 fetcher 함수는 SWR의 key를 받을 수 있게끔 작성해야 한다. 그래야 SWR이 이 key에 따라서 캐시를 관리하고 fetch하게 된다.
3. 데이터 가져오기
그럼 이제 Todo App을 만드는 상황에서 데이터를 가져와서 사용해보자.
첫번째 key에는 todo목록을 가져오는 파라미터인 '/todos를, 두번째 인자에는 위에 만든 fetcher 함수를 넣어줬다.
그러면 왼쪽의 data에는 반환된 데이터인 todo목록이 담기게 되고, 만약 실패하면 error가 반환되어 error에 담긴다.
const {data, error} = useSWR('/todos',fetcher);
이렇게 작성된 TodoList의 전체 코드는 다음과 같다.
(useSWR로 받아온 Todo목록 데이터를 map 함수를 사용해 뿌려주고있다. )
4. 재사용 (함수로 만들어서 사용하기)
export function useTodo(id: string) { const {data,error}= useSWR(`/todos/${id}`,fetcher); return { todo:data, isLoading: !error && !data, isError: error, } }
swr 커스텀 함수
만약 다양한 곳에서 서버 데이터를 가져와 사용해야 한다면 useSWR을 함수로 안에 집어넣어서 커스텀 함수를 만들 수 도 있다.
아래 useTodo함수는 id를 인자로 넣게되면 swr의 key에 들어가게 되고 그 key에 맞게 서버의 데이터 캐싱이 이루어진다.
그러니까 서버의 url이 담긴 fetcher라는 함수를 한번만 작성하고 나면, 나머지는 swr을 사용하여 key에 따라 커스텀 함수를 만들어 사용하면 된다. 그러면 신경쓸 필요없이 swr이 알아서 캐시를 관리해준다. 또한, 위에 보이는것처럼 리턴값을 객체로 만들어 todo, isLoading, is Error로 등으로 만들어 내보내면 사용하는 쪽에서 편리하게 쓸 수 있다.
커스텀 swr 사용!
그런데 커스텀 함수 밑에 빨간줄을 보면, 아까전에 만든 useSWR을 다른페이지인 Detail 페이지에서 또 사용하고 있다.
하지만 괜찮다. SWR은 자동으로 알아서 캐시를 관리하여, 필요없는 중복되는 요청은 하지않도록 되어있다.
swr 공식 사이트의 설명
만약 swr이 못미덥거나 자신의 입맛대로 data를 fetch하고싶은 사람들을 위해 정말 다양한 옵션들이 준비되어있다.
옵션은 useSWR의 3번째 인자로 넣어서 사용할 수 있다.
예를 들어 dedupingInterval 옵션을 주게 되면 값으로 할당한 시간동안 동일한 key의 데이터요청을 막을 수 있다.
const {data, error} = useSWR('/todos',fetcher,{dedupingInterval: 3000});
3초동안 fetch요청이 되지 않는 화면
처음 진입했을때만 서버로부터 데이터를 가져오고 설정한 3초동안은 데이터 요청이 이루어지지 않는것을 볼 수 있다.
이외에도 mutate를 사용하여 화면 랜더링을 갱신하는것도 편리하였고, 전체적으로 매우 만족스러운 라이브러리였다. 서버상태를 따로 관리하지않고 필요한곳에서 사용하는 편이 백엔드 서버를 최대한 활용하는 면에서도 좋아보였다.