Javascript

TanStack/React-Query를 전역 상태 관리자로 사용 가능한가?

드리프트2 2024. 8. 4. 16:33

 

 

최근 웹 개발 커뮤니티에서는 React-Query를 독립적으로 사용하는 것과 다른 상태 관리 라이브러리와 함께 사용하는 것 사이의 장단점을 논의하는 데 많은 관심이 집중되어 왔습니다.

 

특히, React-Query를 전역 상태 관리자로 사용할 수 있는지에 대한 질문은 많은 논쟁을 불러일으키고 있습니다.

질문 요지

한 개발자가 React-Query와 다른 상태 관리 라이브러리(현재는 react-context-selector 사용 중)를 함께 사용할지, 아니면 React-Query만을 사용할지 고민하고 있습니다.

 

이 개발자는 서버에서 많은 데이터를 가져와 클라이언트 측에서 다양한 조작이 필요한 웹 기반 차팅 도구를 개발 중입니다.

 

예를 들어 사용자가 백엔드에서 차트의 모든 노드를 로드한 다음, 차트에 노드를 추가하고 사용자의 입력에 따라 모달을 열 수 있습니다.

 

이러한 경우에 Redux/RTK/RTK-Query의 복잡성과 보일러플레이트 코드 때문에 사용을 꺼리고 있으며, React-Query만으로 충분하다는 주장에 어떻게 대처해야 할지 이해하기 어렵다고 합니다.

 

커뮤니티의 다양한 의견

1. React-Query의 역할과 한계

 

일부 사용자는 React-Query가 서버 데이터와 클라이언트 데이터를 동기화함으로써 사실상의 상태 관리자 역할을 한다고 주장합니다. 그러나 이 데이터를 프론트엔드에서 어떻게 다루는지는 여전히 개발자의 몫입니다. 복잡한 웹 애플리케이션에서는 React-Query만으로는 부족할 수 있으며, 전역 상태와 클라이언트 상태를 모두 관리할 때 두 가지 라이브러리를 사용하는 것이 더 깔끔할 수 있습니다.

아래 예제에서는 React-Query를 사용하여 서버에서 데이터를 가져오는 동시에, React Context를 사용하여 클라이언트 상태를 관리하는 방법을 보여줍니다.

 

이는 React-Query가 전역 상태 관리에 대한 모든 요구사항을 충족시키지 못할 때 다른 상태 관리 도구와의 결합을 예시합니다.

 

코드 예제: React-Query와 React Context를 결합한 사용

이 예제에서는 사용자 목록을 불러오는 API 호출을 처리하고, 선택된 사용자의 ID를 전역 상태로 관리하는 방법을 보여줍니다.

import React, { createContext, useContext, useState } from 'react';
import { useQuery } from 'react-query';

const UserContext = createContext();

// 사용자 ID를 관리하기 위한 컨텍스트 프로바이더
const UserProvider = ({ children }) => {
  const [selectedUserId, setSelectedUserId] = useState(null);

  const value = { selectedUserId, setSelectedUserId };

  return <UserContext.Provider value={value}>{children}</UserContext.Provider>;
};

// 사용자 데이터를 불러오는 API 함수
const fetchUsers = async () => {
  const response = await fetch('https://api.example.com/users');
  if (!response.ok) {
    throw new Error('Network response was not ok');
  }
  return response.json();
};

// 사용자 목록을 표시하고 선택한 사용자 ID를 전역 상태로 설정하는 컴포넌트
function UserList() {
  const { data: users, isLoading, isError, error } = useQuery('users', fetchUsers);
  const { setSelectedUserId } = useContext(UserContext);

  if (isLoading) return <div>Loading...</div>;
  if (isError) return <div>Error: {error.message}</div>;

  return (
    <ul>
      {users.map(user => (
        <li key={user.id} onClick={() => setSelectedUserId(user.id)}>
          {user.name}
        </li>
      ))}
    </ul>
  );
}

// 애플리케이션의 메인 컴포넌트
function App() {
  return (
    <UserProvider>
      <div>
        <h1>Users</h1>
        <UserList />
      </div>
    </UserProvider>
  );
}

설명

이 예제에서는 다음과 같은 작업을 수행합니다:

  1. React Context: UserProvider 컴포넌트는 전역 상태로 선택된 사용자 ID를 관리합니다. 이 상태는 어플리케이션의 다른 부분에서 접근할 수 있으며, 사용자가 목록에서 특정 사용자를 클릭할 때 업데이트됩니다.
  2. React-Query: useQuery 훅은 외부 API에서 사용자 데이터를 비동기적으로 불러옵니다. 데이터가 로딩 중이거나 에러가 발생했을 때 적절한 UI를 제공합니다.

이 구조를 통해 복잡한 애플리케이션에서 React-Query의 데이터 패칭 기능과 다른 상태 관리 방법을 효과적으로 조합할 수 있습니다.

 

React-Query가 제공하는 데이터 캐싱 및 동기화 기능과 함께 클라이언트 상태 관리를 위해 React Context를 사용하는 것은 효율적인 전략이 될 수 있습니다.

 

 

2. 다른 상태 관리 솔루션과의 비교

 

RTK Query와 같은 도구는 구조화되고 문서화된 관례를 제공하여 상태의 읽기, 업데이트 및 유지 관리, 서버 사이드 렌더링 처리, 리액트 리렌더링 최적화, 보일러플레이트 최소화 및 디버깅을 용이하게 합니다.

 

아래 예제는 RTK Query의 강력한 기능을 활용하여 상태 관리를 간소화하고, 효율적인 데이터 패칭 및 캐싱을 수행하는 방법을 보여줍니다.

 

RTK Query를 사용한 데이터 패칭 및 상태 관리 예제

RTK Query를 사용하여 서버에서 사용자 데이터를 가져오고, 이 데이터를 Redux 스토어에 자동으로 캐싱하는 예제입니다.

 

이 예제에서는 RTK Query의 API 슬라이스를 생성하고, 컴포넌트에서 해당 데이터를 조회하는 방법을 다룹니다.

import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';
import { configureStore } from '@reduxjs/toolkit';
import { Provider, useSelector } from 'react-redux';
import React from 'react';

// API 슬라이스 설정
const api = createApi({
  reducerPath: 'api',
  baseQuery: fetchBaseQuery({ baseUrl: 'https://api.example.com/' }),
  endpoints: (builder) => ({
    getUsers: builder.query({
      query: () => 'users',
    }),
  }),
});

// 스토어 생성
const store = configureStore({
  reducer: {
    // API 슬라이스 리듀서 등록
    [api.reducerPath]: api.reducer,
  },
  // 미들웨어 등록
  middleware: (getDefaultMiddleware) =>
    getDefaultMiddleware().concat(api.middleware),
});

// 사용자 목록을 보여주는 컴포넌트
function UsersComponent() {
  const { data: users, error, isLoading } = api.useGetUsersQuery();

  if (isLoading) return <div>Loading...</div>;
  if (error) return <div>Error: {error.message}</div>;

  return (
    <ul>
      {users.map(user => (
        <li key={user.id}>{user.name}</li>
      ))}
    </ul>
  );
}

// 애플리케이션의 메인 컴포넌트
function App() {
  return (
    <Provider store={store}>
      <div>
        <h1>Users</h1>
        <UsersComponent />
      </div>
    </Provider>
  );
}

export default App;

설명

이 코드에서 수행되는 주요 작업은 다음과 같습니다:

  1. API 슬라이스 설정: createApi 함수를 사용하여 API 슬라이스를 생성합니다. fetchBaseQuery는 기본적인 패칭 로직을 제공하며, endpoints는 API 엔드포인트를 정의합니다. 여기서는 getUsers 쿼리를 통해 사용자 목록을 가져옵니다.
  2. 스토어 생성: Redux 스토어를 생성하고 API 슬라이스의 리듀서와 미들웨어를 스토어에 등록합니다. 이는 RTK Query의 상태 관리 및 캐싱 기능을 활성화합니다.
  3. 컴포넌트에서의 데이터 조회: useGetUsersQuery 훅을 사용하여 컴포넌트에서 사용자 데이터를 조회합니다. 이 훅은 서버 상태를 로컬 상태처럼 쉽게 사용할 수 있게 해 줍니다.

RTK Query는 서버 사이드 렌더링, 보일러플레이트 최소화, 강력한 타이핑, 캐싱, 데이터 동기화 등을 지원하여 복잡한 상태 관리 요구사항을 쉽게 해결할 수 있도록 도와줍니다.

 

이러한 기능은 대규모 애플리케이션 개발 시 개발자의 생산성을 크게 향상시킬 수 있습니다.

 

3. 실제 사용 사례

 

일부 개발자는 React-Query를 상태 관리 도구로만 사용하면서 전역 컨텍스트를 여러 개 운영하는 복잡한 애플리케이션을 구축한 경험이 있습니다.

 

그러나 이 경우에도 클라이언트 측에서 복잡한 로직을 처리하기 위해 추가적인 상태 관리 솔루션이 필요할 수 있습니다.

코드 예제: React-Query를 사용한 데이터 관리

React-Query를 사용하여 API에서 데이터를 가져오고, 클라이언트 상태를 관리하는 간단한 예제입니다.

import { useQuery } from 'react-query';

const fetchUserData = async () => {
  const response = await fetch('https://api.example.com/user');
  if (!response.ok) {
    throw new Error('Failed to fetch user');
  }
  return response.json();
};

function UserComponent() {
  const { data: user, isLoading, isError, error } = useQuery('user', fetchUserData);

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

  if (isError) {
    return <div>Error: {error.message}</div>;
  }

  return (
    <div>
      <h1>{user.name}</h1>
      <p>Email: {user.email}</p>
    </div>
  );
}

 

이 코드는 사용자 데이터를 서버에서 가져와 화면에 표시합니다.

 

React-Query의 캐싱 기능 덕분에, 데이터가 이미 존재할 경우 네트워크 요청 없이 즉시 데이터를 제공할 수 있습니다.

 

결론

React-Query는 데이터 패칭과 캐싱에 강력한 도구입니다만, 모든 상태 관리 요구사항을 충족시키지는 못할 수 있습니다.

 

보다 복잡하고 상호작용이 많은 웹 애플리케이션을 구축할 때는 React-Query를 보완할 수 있는 다른 상태 관리 라이브러리를 고려하는 것이 좋습니다.

 

이는 데이터 관리의 효율성을 극대화하고 더 나은 사용자 경험을 제공할 수 있습니다.