[React] SWR: 전역 저장소로써 사용해보기

2022. 7. 29. 17:25React/클론코딩

내가 맡았던 프로젝트가 그렇게 규모가 컸던 적이 많이 없었어서 여태까지 전역 저장소를 써본 적이 없다.

처음으로 SWR을 써봤는데 이거 상당히 히트다.

 

https://swr.vercel.app/ko/docs/getting-started

 

시작하기 – SWR

시작하기 React 프로젝트 폴더 안에서 다음을 실행하세요. npm을 사용한다면 JSON 데이터를 사용하는 일반적인 RESTful API라면 먼저 네이티브 fetch의 단순한 래퍼인 fetcher 함수를 생성해야 합니다. cons

swr.vercel.app

 

0. 기본적인 사용법

import useSWR form "swr"

...
const { data, error, mutate } = useSWR("YOURKEY", fetcher);

 

key에는 보통 api 주소를 넣어준다.

흐름은 이런 식이다.

  1. fetcher에 axios 등을 이용한 비동기, 동기 함수를 만든다. (이때 꼭 return하는 data가 있어야 한다.)
  2. key를 바탕으로 해당 주소로 GET, PUSH 등 요청을 보낸 뒤, data에 저장한다.
  3. 전역으로 저장된 데이터를 다양한 컴포넌트에서 그대로(key를 똑같이 선언해주면 data로) 사용할 수 있다.

처음에 딱 보고 느낀게,

props drilling 등이 언제나 문제인 React 환경에서 이렇게 GET 요청을 많이 보내도 될까? 이런게 걱정이었다. (기본적으로는 해당 주소로 통신하는 걸 목적으로 하니..)

 

그러나, dedpuingInterval option을 조정하면서 해결이 가능하다!

const { data, error, mutate } = useSWR("YOURKEY", fetcher, {
    dedupingInterval: 1000000,
  });

 

dedupingInterval의 default 값은 2000ms이다. 이 기간동안은 어느 컴포넌트에서 몇 번을 호출해도 저장되어있는 캐시에서 값을 불러오고, 다시 요청을 보내지 않는다고 한다. 로그인을 했을 때 유저 정보(이름이나, 생년월일, 프로필 이미지 주소 등)을 받아오면 그 값을 data에 넣어보자! 인생이 편해질 것 같다.

 

이전 프로젝트에서는 서버에서 이런 값들을 세션값으로 만들어서 쿠키에 넣어줬었는데 약간 불안한 느낌이 들었다.

개인정보가 그대로 노출되는 느낌이 들어서.. 이런 방식은 일단 쿠키에 정보가 남지 않아서 정말 좋다.

 

1. mutate에 대해서

axios.post("/api/userinfo", {email, password}, {withCredentials: true})
      .then((res) => {
        mutate(res.data, false);
      })

 

기본적으로 SWR을 세팅하고나면 매번 GET 요청을 보내야한다.

그러니까 그냥 컴포넌트가 mount 될때부터 시작해서 dedupingInterval 시간이 종료될때마다 계속 요청을 보낸다. 이건 필요없는 요청을 여러번 보내야하는 불편함과 비효율의 끝이다. 이건 개선을 할 수 있지 않을까?

 

예를 들어 로그인에 성공했을 때 response를 저장해두면 굳이 매번마다 유저의 정보를 다시 보낼 필요가 있을까? 그 정보를 전역 저장소에 저장했다가 필요한 컴포넌트에서 꺼내쓰면 해결할 수 있을 것이다.

 

이럴 때 mutate를 이용할 수 있다. 해당 api 주소를 key로 설정해두고, login에서 받은 response를 저장해둬보자!

필요없이 여러번 반복적으로 호출되는 SWR 요청을 막을 수 있다.

 

기본적으로 mutate의 revalidate 옵션은 true이다. 만약 별다른 설정없이 mutate를 써준다면, 내가 의도한 위치에서 GET요청을 보내서 정보를 받아올 것이다. 그러나 이 마저도 비효율적이라고 느낀 당신! 두번째 인자를 false로 넣어줘보자.

의도한 위치에서 따로 GET 요청을 보내지 않아도 의도한 데이터를 얻을 수 있다면..!

(예를 들어, 로그인 성공 시 사용자 정보를 넣는 경우, 굳이 userInfo를 GET하지 않아도 된다.) 

 

2. 다양한 활용법에 대해서

SWR을 잘 사용하는가?

SWR은 단순히 비동기 axios 처리만을 위한 라이브러리가 아니다.

localStorage에서 값을 가져온다던가,

아니면 같은 주소에서 다른 느낌으로 data를 가공하고 싶은 경우

//response

{
  name: "Jake",
  nationCode: 82,
  phoneNumber: 109999999,
  favorites: [
    {
    	id: 52,
        name: "Bailey"
    },
  ]
}

 

뭐 이런 자료가 있을 때 어디에선 이름만 활용하고 어딘가에선 favorites를 활용하고 싶은 경우가 있다면 각각 다르게 쓰는 방법도 있다고 한다. key를 약간의 꼼수로 다르게 활용할 수 있다.

// usecase 1
const { data } = useSWR("/api/userinfo", fetcher1);

// usecase 2
const { data } = useSWR("/api/userinfo?favorite=true", fetcher2);

// usecase 3
const { data } = useSWR("/api/userinfo#82", fetcher3);

이런 식의 queryString을 붙여주는 식으로도 활용이 가능하다.

서버에서는 ?나 # 뒤의 값들은 다 무시가 된다고 한다. 그러니 결과적으로는 다 같은 주소(/api/userinfo)에서 같은 response를 가져온다. 그러나 fetcher가 다 다르다. 각각 불러온 response를 적절하게 가공해줘서 입맛에 맞게 써주면 되겠다.

 

진작 배울걸.. 괜히 미뤘다는 생각이 든다.

앞으로 인생이 편해질 듯 하다.