본문 바로가기

TIL

TIL - 상태 관리 도구 비교: Redux, Zustand, React Query

이번 TIL에서는 React 애플리케이션에서 널리 사용되는 상태 관리 도구인 Redux, Zustand, React Query에 대해 알아보고, 각 도구의 장단점과 사용 예시를 정리하겠습니다. 또한, 클라이언트와 서버 상태 관리를 설명하며 예시 코드를 제공하겠습니다.


목차

  1. 상태 관리 개요
  2. Redux vs. Zustand vs. React Query 비교
    • Redux
    • Zustand
    • React Query
  3. 서버 상태 관리와 클라이언트 상태 관리
  4. 사용 예시
    • 로그인 상태 관리 예시
    • 게시글 작성 예시
  5. 대규모 애플리케이션에서의 상태 관리
  6. 표와 다이어그램
    • 상태 관리 도구 비교 표
    • 상태 관리 다이어그램
  7. 결론

1. 상태 관리 개요

애플리케이션에서 상태 관리는 중요한 역할을 합니다. 상태 관리 도구는 중앙에서 상태를 관리하고, 데이터를 업데이트하며, 컴포넌트 간 상태를 공유할 수 있게 도와줍니다. 상태 관리는 크게 클라이언트 상태 서버 상태로 나눌 수 있습니다.

  • 클라이언트 상태: 사용자 인터페이스와 관련된 상태를 관리합니다. 예를 들어, 사용자 입력, UI의 로딩 상태 등을 다룹니다.
  • 서버 상태: 서버에서 가져오는 데이터를 관리합니다. 예를 들어, API 호출을 통해 가져온 데이터를 저장하고, 캐싱 및 갱신하는 데 사용됩니다.

2. Redux vs. Zustand vs. React Query 비교

Redux

Redux는 중앙집중식 상태 관리를 위한 가장 널리 사용되는 도구 중 하나입니다.

장점:

  • 중앙집중식 상태 관리: 애플리케이션 전체 상태를 한 곳에서 관리.
  • 예측 가능성: 액션과 리듀서의 조합으로 상태 변화가 예측 가능.
  • 미들웨어: redux-thunk나 redux-saga 같은 미들웨어로 비동기 로직 처리 가능.

단점:

  • 보일러플레이트 코드: 설정과 작성해야 할 코드가 많음.
  • 복잡성: 작은 애플리케이션에서는 오히려 복잡하게 느껴질 수 있음.

Zustand

Zustand는 간결하고 경량의 상태 관리 라이브러리입니다.

장점:

  • 경량: 상태 관리를 위한 코드가 간결하고 설정이 쉬움.
  • 간단한 API: 작은 규모의 애플리케이션에 적합.
  • Hooks 기반: React의 hooks와 잘 통합됨.

단점:

  • 대규모 애플리케이션: 규모가 커질수록 상태 관리가 복잡해질 수 있음.
  • 커뮤니티와 생태계: 리덕스만큼의 큰 커뮤니티와 생태계는 아직 부족함.

React Query

React Query는 서버 상태 관리를 위한 라이브러리입니다.

장점:

  • 서버 상태 관리에 최적화: 서버에서 데이터를 가져오고, 캐싱, 동기화, 업데이트 등을 자동으로 처리.
  • 자동화된 캐싱: 불필요한 네트워크 요청을 줄여 성능 최적화.
  • 비동기 데이터 처리: 비동기 데이터를 쉽게 관리할 수 있음.

단점:

  • 클라이언트 상태 관리에는 적합하지 않음: 주로 서버에서 가져오는 데이터를 관리하는 데 사용됨.

3. 서버 상태 관리와 클라이언트 상태 관리

서버 상태 관리는 주로 서버에서 데이터를 가져오고 관리하는 데 사용됩니다. React Query가 대표적인 도구입니다.

  • 데이터 캐싱: 서버 데이터를 캐싱하여 불필요한 네트워크 요청을 줄임.
  • 자동 갱신: 서버 데이터가 변경되면 자동으로 캐시를 갱신함.

클라이언트 상태 관리는 애플리케이션의 UI와 사용자 입력 상태를 관리합니다. Zustand Redux가 주로 사용됩니다.

  • UI 상태 관리: 로딩 상태, 에러 상태 등을 관리.
  • 사용자 입력 관리: 입력 필드의 데이터 등을 관리.

4. 사용 예시

로그인 상태 관리 예시

클라이언트 상태 관리: 로그인 상태와 관련된 사용자 정보를 관리.

서버 상태 관리: 로그인 API 호출을 통해 서버에서 사용자 인증 정보를 가져옴.

게시글 작성 예시

클라이언트 상태 관리: 사용자 입력 필드를 관리.

서버 상태 관리: 작성된 게시글을 서버에 전송하고, 서버에서 데이터를 갱신.

import { useMutation, useQueryClient } from 'react-query';
import { useState } from 'react';
import { postNewArticle } from './api'; // 게시글 작성 API 호출 함수

function CreateArticle() {
  const [title, setTitle] = useState('');
  const [content, setContent] = useState('');
  const queryClient = useQueryClient();

  const mutation = useMutation(postNewArticle, {
    onSuccess: () => {
      // 쿼리 무효화로 데이터 갱신
      queryClient.invalidateQueries('articles');
    },
  });

  const handleSubmit = (e) => {
    e.preventDefault();
    mutation.mutate({ title, content });
  };

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="text"
        value={title}
        onChange={(e) => setTitle(e.target.value)}
        placeholder="Title"
      />
      <textarea
        value={content}
        onChange={(e) => setContent(e.target.value)}
        placeholder="Content"
      />
      <button type="submit">Submit</button>
    </form>
  );
}

5. 대규모 애플리케이션에서의 상태 관리

대규모 애플리케이션에서는 상태 관리를 체계적으로 해야 합니다. 예를 들어, 상태를 잘 구조화하고, 상태 간의 의존성을 명확히 관리해야 합니다.

Zustand의 대규모 애플리케이션에서의 한계

Zustand는 간단하고 직관적인 API를 제공하지만, 대규모 애플리케이션에서는 상태 관리가 복잡해질 수 있습니다.

예시 코드:

import create from 'zustand';

// 단일 스토어에 너무 많은 상태를 관리하는 예시
const useStore = create(set => ({
  products: [],
  cart: [],
  user: null,
  orders: [],
  setProducts: (products) => set({ products }),
  addToCart: (product) => set(state => ({ cart: [...state.cart, product] })),
  setUser: (user) => set({ user }),
  addOrder: (order) => set(state => ({ orders: [...state.orders, order] })),
}));

// 컴포넌트에서 상태를 사용하는 예시
function ProductList() {
  const { products, setProducts } = useStore();
  // 제품 목록을 불러와서 상태 업데이트
  useEffect(() => {
    fetchProducts().then(setProducts);
  }, []);
  return (
    <ul>
      {products.map(product => (
        <li key={product.id}>{product.name}</li>
      ))}
    </ul>
  );
}

function Cart() {
  const { cart, addToCart } = useStore();
  return (
    <div>
      <h2>Cart</h2>
      <ul>
        {cart.map(item => (
          <li key={item.id}>{item.name}</li>
        ))}
      </ul>
      <button onClick={() => addToCart({ id: 1, name: 'Product 1' })}>Add to Cart</button>
    </div>
  );
}

6. 표와 다이어그램

상태 관리 도구 비교 표

도구장점단점사용 예시

도구 장점 단점 사용예시
Redux 중앙집중식 상태 관리, 예측 가능성 보일러플레이트 코드 많음, 복잡함 대규모 애플리케이션
Zustand 경량, 간단한 API, Hooks 기반 대규모 애플리케이션에서 복잡해짐 소규모 애플리케이션
React Query 서버 상태 관리에 최적화, 자동화된 캐싱 클라이언트 상태 관리에는 적합하지 않음 서버 데이터 관리, 캐싱

 

상태 관리 다이어그램

 

Redux 상태 관리 다이어그램: 중앙 집중식 상태 관리, 상태 업데이트를 위한 액션과 리듀서를 포함

Redux 상태 관리 다이어그램

 

 

Zustand 상태 관리 다이어그램: 간단하고 경량의 상태 관리, 훅을 이용한 상태 업데이트.

Zustand 상태 관리 다이어그램

 

React Query 상태 관리 다이어그램: 서버 상태 관리, 데이터 페칭과 캐싱을 중심으로 하는 구조.

 

React Query 상태 관리 다이어그램

 

7. 결론

이번 TIL에서는 Redux, Zustand, React Query를 비교하고, 각각의 장단점을 분석했습니다. 클라이언트 상태와 서버 상태의 관리 방식을 이해하고, 다양한 예시를 통해 상태 관리 도구를 어떻게 사용할 수 있는지 살펴보았습니다.