ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • TanStack/React-Query를 전역 상태 관리자로 사용 가능한가?
    Javascript 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를 보완할 수 있는 다른 상태 관리 라이브러리를 고려하는 것이 좋습니다.

     

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

Designed by Tistory.