비동기 전역관리 redux 말고 편하게 SWR 로!

column clash·2021년 7월 20일
1

추후 REDUX 에 대해서도 다루면서
Redux Toolki 과 Redux Thunk, Redux Saga 사용법에
대해서도 다루어보겠지만,

이 글에서는 SWR 내용을 정리해보고자 한다.

SWR 은 NEXTJS 를 만든 VERCEL 에서 만든 데이터 패치
라이브러리다.

홈페이지에 가보면
"데이터 가져오기를 위한 React Hooks" 이라고 되있다!

서버에 데이터를 보내거나 가져오려면
axios 등의 프로그램으로 (혹은 fetch나) .get .post 등으로 통신하면 된다.

그리고 나서 response.data 를
useState등에 담아서 화면에 그려내면 되는데,

통신된 데이터가 만약 그 컴포넌트안에서만 쓰이는 게 아니라,
싸이트다 보니, 메인페이지에서도 사용되고, about 페이지에서도
사용되고 한다고 하자.

그럼 그때마다 axios 로 각각 받아서 useState등으로 다시
담아서 쓰느냐? 라고 할 수 있다.

즉, 전역 데이터 관리는 어떻게 할 것인가?

가장 최상위 컴포넌트에서 자식에게 pros 로 보내주며
pros drilling 을 하는게 전역 데이터 관리에 대한 체계가 없을때
하던 짓이었다.

공식 홈페이지에서 REACT 로 생각하기편을 보면,
props 로 데이터를 내려준다.

자식 컴포넌트가 부모 컴포넌트에게 상태값에 변화를 주려면
함수를 보내준 후, 그것을 통해서 변화를 줄 수 있는데.

문제는 부모-자식하고의 관계만으로는 그렇게 되는데,

증손자뻘 되는 애들에게는 그짓을 하기가 너무 번거러워지는 것이다.

그래서, 전역관리를 위해서 context api 도 있고, redux 도 있다.

redux는 동기 프로그램의 상태변화를 위해서 처음 만들어졌다보니, 비동기 상태를 위해선 미들웨어가 필요했고,
미들웨어는 위에서 말한 redux thunk 하고 redux saga 등이
비동기 상태를 위한 대표적인 미들웨어다.

redux 를 과연 왜 쓰는 걸까 생각이 든다면,
서비스 하나를 직접 제작하다보면,
어라 이 데이터는 여기도 쓰이고 저기도 쓰이는데
하는 부분이 존재할 거고,

관심사의 분리를 하고 싶은 욕망이 들기도 할테니
그럴때 redux 를 써보면 개 편하군 이란 생각이 들거다.

react 를 익히다보면, react 를 익히는 것보다
redux 를 익히는 시간이 초반에 더 많아서

redux 이 어려운 걸 왜 쓰는거야 라고 생각이 들수도 있지만,

극단적으로 생각해서,
html 에서 .js 를 나눠서,
html 코드는 html 코드만, js는 js에만 있듯이

action => dispatch => reducer => store => view (flux) 를 통해서
(내가 작업할때는 주로 action, reducer, store 작업을 해주고, 컴포넌트에서 dispatch 를 이벤트콜백해주는 식)

컴포넌트에는 dispatch 해주고, 리덕스 에서 로직이 있게
만들어두면, 전역에서 쓸 수 있게 된다고 생각한다면,
의외로 쉽게 익힐 수 있다.

특히나 redux toolkit 으로 넘어오면서 어려울 게 없어졌다.

다만, 그럼에도...
이해는 쉽게 할 수 있지만, 코드도 길고, 저 긴 과정으로
하는 것이 사람들의 편리함에 대한 욕구를 건드리고 있었다.

그러다 이 swr 이 나온 것이다. 두둥.

swr 은 매우 간단하다!

코드를 보자.

import useSWR from 'swr'
import axios from 'axios'

function Profile() {
const fetcher = url => axios.get(url).then(res => res.data)
const { data, error } = useSWR('/api/user', fetcher)

  if (error) return <div>failed to load</div>
  if (!data) return <div>loading...</div>
  return <div>hello {data.name}!</div>
}

이게 끝이다~!

axios.get(url) 여기서 이 url 은
useSwr('/api/user <-- 이 부분이 들어간다.

일단, 간단하고 심플하다!

전역관리 방법도 쉽다.
swr 홈페이지에서는 다음과 같이 쓰라고 되있다.
(시작하기 - 재활용하게 만들기)

hook 폴더를 만든 후, 거기에 useUser.js 하나 만들자.

function useUser (id) {
  const { data, error } = useSWR(`/api/user/${id}`, fetcher)

  return {
    user: data,
    isLoading: !error && !data,
    isError: error
  }
}

그리고는 필요한 곳에서,

function Avatar ({ id }) {
  const { user, isLoading, isError } = useUser(id)

  if (isLoading) return <Spinner />
  if (isError) return <Error />
  return <img src={user.avatar} />
}

이렇게 쓰면 된다.

만약, 상품을 등록하자 마자, 화면에 렌더링 하고 싶다 그러면 어떻게 사용할 수 있을까?

useProduct.js

import axios from "axios";
import useSwr from "swr";

function useProduct() {
  const fetcher = async (url) => {
    const resp = await axios.get(url);
    return resp.data;
  };
  const { mutate, data, error } = useSwr(`/api/product/product/`, fetcher);
  return {
    mutate: mutate,
    product: data,
    isLoading: !error && !data,
    isError: error,
  };
}

export default useProduct;

admin/product.js

function product() {
  const { product, mutate, isLoading, isError } = useProduct();
  const [name, setName] = useState("");
  const createItem = async (e) => {
    mutate([...product, { name }], true);
    const resp = await axios.post("/api/product/product", { name });
      };
      const onChange = useCallback((e) => {
    setName(e.target.value);
  }, []);
  
 if (isLoading) return <Spinner />
  if (isError) return <Error />
  return (
    <div>
      <Counter />
      <input name="name" placeholder="name" onChange={onChange} value={name} />
      <ul>
        {product?.map((x, i) => (
          <li>
            {x._id} {x.name}
          </li>
        ))}
      </ul>
      <div>
        <button onClick={createItem}>저장</button>
      </div>
    </div>
  );
}

export default product;

이렇게 hook 으로 만들어두면, product 컴포넌트에서도
Counter 컴포넌트에서도 서버호출 없이 전역으로 사용이 가능해진다.

mutate 는 서버에서 응답값을 받기전에, 화면을 먼저 그려놓고,
true 일때는 서버에서 응답이 오면 그 내용을 받아서 랜더링 해주고,
false 를 해두면 그려놓고 서버에만 값을 보내는 것을 종료된다.

비동기는 더이상 redux-saga 와 redux-thunk 가 아닌 swr 로
편하게 사용가능하며, 창 포커싱시 자동 업데이트등 다양한 부가적인
기능을 제공하고 있으니,더 자세한 내용은

공식 홈페이지를 보면 쉽게 쓸 수 있는 그저 매우 좋은 '라이브러리'일뿐이다.

https://swr.vercel.app/ko/docs/getting-started#%EC%9E%AC%EC%82%AC%EC%9A%A9-%EA%B0%80%EB%8A%A5%ED%95%98%EA%B2%8C-%EB%A7%8C%EB%93%A4%EA%B8%B0

다음 글에서는, input 여러개 사용시 useInput 훅을 만들어
swr 사용하는 것으로 글을 적어보겠다.

profile
풀스택 개발 중...

0개의 댓글