Posts React 프로젝트에 SWR사용하기
Post
Cancel

React 프로젝트에 SWR사용하기

SWR(stale-while-revalidate)은 클라이언트 서버에서 data를 가져오는 기능(fetching)을 편리하게 사용할 수 있도록 도와주는 hook이다. 백서버에서 GET요청을 하고 결과를 받아올 때 간편하게 쓸 수 있어 react프로젝트를 할 때 사용했다.

redux의 reducer나 saga로 만들면 코드량이 길어질 것을 짧은 코드로 사용할 수 있다. next팀이 만들어 nextjs와 호환이 잘 된다. SWR은 클라이언트 서버에서만 사용할 수 있어서 POST, PATCH, DELETE 등 데이터베이스의 데이터를 바꿔야할 경우에는 기존의 redux로 요청을 보내야한다.

내 프로젝트의 경우 지인으로부터 menu의 탭을 클릭하고 나서 한참 있다가 클릭한 탭의 색이 변하고 닉네임을 수정하고나서 한참 있다가 수정사항이 반영되서 불편했다는 말을 듣고 브라우저 성능 최적화를 위해 SWR을 도입하기로 했다. 이 두 가지 문제 모두 백서버에 POST요청을 보내는 기능에서 발생했음에도 백서버에서 데이터를 가져오기 전에 클라이언트 화면을 SWR을 이용해 빠르게 바꾸어주도록 하기 위해서였다.
따라서 SWR로 클라이언트 서버의 중앙데이터를 관리하는 redux에 있는 initialState 객체의 데이터값을 먼저 바꿨다가 SSR이 끝나면 백서버에서 가져온 데이터는 saga와 reducer가 다시 넣어준다.

다음 예는 initialState의 속성 중 하나인 nickname의 값을 SWR에서 제공하는 mutate로 먼저 바꾸고 동시에 react-redux에서 제공하는 useDispatch로 백서버에 POST요청을 보내는 부분이다.

../reducers/user.js

1
2
3
4
5
export const initialState = {
  me: {
    nickname: "닉네임",
  },
};

useSWR 훅을 사용할 때 원래 “globalState”의 자리에는 요청을 보낼 주소를 적어주는데 local-state를 공유할 때는 저렇게 mutate하고만 이름을 일치시켜주면 된다. 참고로 mutate가 실행되면 “http://localhost:3000/globalState”로 요청이 간다. 저런 주소는 프론트서버에는 없기때문에 요청 에러 문구가 콘솔에 뜨지만 initialData에 import한 initialState의 값을 대입해주면 redux의 중앙데이터인 initialState를 가져다 쓰고 바꿀 수 있다.

../components/NicknameEditForm.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
import { useDispatch, useSelector } from "react-redux";
import useSWR, { mutate, trigger } from "SWR";
import { initialState, CHANGE_NICKNAME_REQUEST } from "../reducers/user";

const NicknameEditForm = ({ onCancel }) => {
  const { data } = useSWR("globalState", { initialData: initialState });

  const dispatch = useDispatch();
  const [nickname, onChangeNickname] = useInput(me?.nickname || "");

  const onSubmit = useCallback(() => {
    mutate(
      "globalState",
      {
        ...data,
        me: { nickname: nickname },
      },
      false
    );
    dispatch({
      type: CHANGE_NICKNAME_REQUEST,
      data: nickname,
    });
    trigger("globalState");
  }, [nickname]);

  return (
    <Form onFinish={onSubmit}>
       <NicknameInputSearch
              value={nickname}
              required
              onChange={onChangeNickname}
            />
        <Button
            htmlType="submit"
            loading={changeNicknameLoading}
            type="primary"
          >
            바꾸기
          </Button> 
    </Form>
  );
};
NicknameEditForm.propTypes = {
  onCancel: PropTypes.func.isRequired,
};
export default NicknameEditForm;

폼을 제출하는 바꾸기 버튼을 클릭하면 mutate가 실행되면서 바뀐 nickname을 {me:{nickname:nickname}} 객체형식으로 보낸다. 보내자마자 데이터를 바꿔주는 것이 아니라 dispatch요청을 보낸 후에 바꾸고 싶어 뒤에 trigger를 붙여줬다. dispatch요청이 보내지면 trigger가 실행되면서 바뀐 데이터 값을 가져와 화면에 그려주게 된다.
SWR을 redux toolkit와 함께 사용하면 redux 상태관리를 더 짧은 코드로 해낼 수 있다고 해 redux toolkit도 공부해서 프로젝트에 도입해볼 예정이다.

참고:
https://SWR.vercel.app/
youtube-2020-feb-SWR-hook
SWR github example: local-state-sharing

This post is licensed under CC BY 4.0 by the author.