2022. 7. 29. 17:25ㆍReact/클론코딩
내가 맡았던 프로젝트가 그렇게 규모가 컸던 적이 많이 없었어서 여태까지 전역 저장소를 써본 적이 없다.
처음으로 SWR을 써봤는데 이거 상당히 히트다.
https://swr.vercel.app/ko/docs/getting-started
0. 기본적인 사용법
import useSWR form "swr"
...
const { data, error, mutate } = useSWR("YOURKEY", fetcher);
key에는 보통 api 주소를 넣어준다.
흐름은 이런 식이다.
- fetcher에 axios 등을 이용한 비동기, 동기 함수를 만든다. (이때 꼭 return하는 data가 있어야 한다.)
- key를 바탕으로 해당 주소로 GET, PUSH 등 요청을 보낸 뒤, data에 저장한다.
- 전역으로 저장된 데이터를 다양한 컴포넌트에서 그대로(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를 적절하게 가공해줘서 입맛에 맞게 써주면 되겠다.
진작 배울걸.. 괜히 미뤘다는 생각이 든다.
앞으로 인생이 편해질 듯 하다.
'React > 클론코딩' 카테고리의 다른 글
[React] 제로초님의 실수를 간파해낸 "나" - nodeJS의 라우터 (0) | 2022.08.24 |
---|---|
[React] 라우터 구조의 설계에 대해서(react-router-dom v6) (0) | 2022.08.21 |
[SWR] revalidate가 없어진 지금 어떻게 데이터를 갱신하는가? (0) | 2022.08.16 |
비밀번호 맞는데 도대체 왜그래...:( Access denied for user 'root'@'localhost'(using password: YES) (0) | 2022.07.29 |
[React 18] React.FC에서 사라진 children.. 왜 맨날 나한테만 말 안해줘!! (0) | 2022.07.28 |