React-Query 튜토리얼

제이든·2022년 2월 25일
4

1. 개요

요즘 핫한🔥 React-Query라는 라이브러리가 있다. 리액트는 본인들이 라이브러리라고 칭하고 있는데... 라이브러리이기 때문에 갖는 단점들이 몇가지 있다. 뷰 이외의 기능들은 직접 구현하거나 써드파티 라이브러리를 사용해야 한다는 점이다. 즉 자유분방하다는 것!

따라서 data-fetching에 관해서도 규칙이 없었다

흔히들 Reduxsaga를 많이 사용하지만 이 또한 정해진 규칙이 없어서 전부 제 각각의 방식으로 데이터를 fetching하고 저장했었다. 또 Redux의 최대 단점은 보일러플레이트 코드가 너무 많다는 것이다. 맨날 리듀서, 액션, 스토어 돌아다니면서 코드를 수정했는데..물론 duck-pattern을 사용할 수도 있지만 모듈자체가 길어질 수 있으므로 pass 😥

하지만 이제는 React-Query를 이용하면 이런 문제점들을 어느 정도 해결해줄거 같다.

그래서 왜 쓰는데요?

React-Query에서 중요한 개념인 Client StateServer State에 대해서 알아보자.

  • Client State
    • client에서만 관리하는 정보들(ex.input의 text)
    • 사용자가 선택한 언어, theme 등
  • Server State
    • Server에서 받아온 모든 데이터

React-Query는 Server State만 관리한다. 리덕스에 익숙하다면 서버 데이터를 받아와서 클라이언트에서 관리해야하는 무언가가 있어야하는거 아닌가? 생각이 들겠지만 그런경우는 극히 드물다!

장점

  1. 클라이언트에서 서버 데이터의 캐시를 관리합니다.

  2. loading, error state를 관리합니다.

  3. pagination, infinite scroll도 쉽게 처리할 수 있도록 지원합니다.

  4. prefetching을 쉽게 처리할 수 있도록 지원합니다.

  5. error가 발생할 경우 자동으로 재시도합니다.

  6. request가 성공하거나 실패했을 때 각각 callback을 정의할 수 있습니다.

어찌보면 1번이 React-Query를 이용하는 가장 큰 이유라고 볼 수도 있겠다. 서버와 프론트의 중간쯤에서 마치 캐시서버같은 역할을 수행해준다.

이제 실제 튜토리얼을 진행하면서 자세하게 사용법을 알아보자.
코드에볼루션 리액트 쿼리를 참고했다.

2. 시작

⚙️ settings

먼저 CRA를 사용할 것이고 패키지 매니저로는 yarn을 사용할 것이다.

npx create-react-app react-query-start
cd react-query-start
yarn init -y

다음으로 data-fetching을 해야하니 서버가 필요한데 JSON-Server를 이용할 것이다.

yarn add json-server

JSON-Server를 설치하고 root에 db.json 파일을 생성하자.

{
  "superheroes": [
    { "id": 1, "name": "Batman", "alterEgo": "Bruce Wayne" },
    { "id": 2, "name": "Spiderman", "alterEgo": "Peter Parker" },
    { "id": 3, "name": "Ironman", "alterEgo": "Tony Stark" }
  ]
}

그리고 package.json에 다음 스크립트를 추가해보자.

 "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject",
    "serve-json": "json-server --watch db.json --port 4000"
  },

yarn serve-json을 입력하고 포트 4000번에서 확인하면 다음 데이터가 존재하는 것을 확인할 수 있다.

서버까지 세팅이 완료되었고, 몇 가지 라우팅을 추가해보자.

yarn add react-router-dom

이제 컴포넌트를 세 가지 추가해보자.
/src/components/ 밑에 Home.page.js, SuperHeroes.page.js, RQSuperHeroes.page.js 를 만든다.

특별한 내용은 없고 세 컴포넌트 모두 다음과 같이 구성한다.

import React from 'react';

function Homepage() {
  return <div>Homepage</div>;
}
export default Homepage;

이제 마지막으로 App.js에 라우팅을 추가해보자.

function App() {
  return (
    <BrowserRouter>
      <div>
        <nav>
          <ul>
            <li>
              <Link to="/">Home</Link>
            </li>
            <li>
              <Link to="/super-heroes">Traditional Super Heroes</Link>
            </li>
            <li>
              <Link to="/rq-super-heroes">RQ Super Heroes</Link>
            </li>
          </ul>
        </nav>
        <Routes>
          <Route path="/super-heroes" element={<SuperHeroes />} />
          <Route path="/rq-super-heroes" element={<RQSuperHeroes />} />
          <Route path="/" element={<Homepage />} />
        </Routes>
      </div>
    </BrowserRouter>
  );
}

간단한 스타일도 적용해보자.
App.css

nav ul {
  display: flex;
  background-color: blanchedalmond;
  margin-block-start: 0;
  padding: 16px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
}

nav ul li {
  list-style-type: none;
  margin-right: 16px;
}

3. 전통적인 data fetching

import axios from 'axios';
import React, { useEffect, useState } from 'react';

function SuperHeroesPage() {
  const [isLoading, setIsLoading] = useState(true);
  const [data, setData] = useState([]);

  useEffect(() => {
    axios.get('http://localhost:4000/superheroes').then((res) => {
      setData(res.data);
      setIsLoading(false);
    });
  }, []);

  if (isLoading) {
    return <h2>Loading...</h2>;
  }

  return (
    <>
      <h2>Super Heroes Page</h2>
      {data.map((hero) => {
        return <div key={hero.name}>{hero.name}</div>;
      })}
    </>
  );
}
export default SuperHeroesPage;

컴포넌트들이 마운트되면 useEffect가 실행되면서 superheroes 엔드포인트로 요청을 보내고 데이터를 받아서 state로 저장하고 화면에 렌더링해서 보여주는 전통적인 방식으로 구현해보았다.

다음 챕터에서는 React-Query를 이용해서 좀 더 간단한 방식으로 구현해보자.

profile
개발자 제이든

0개의 댓글