1. 기존 React 코드로 서버 데이터 관리
useState와 useEffect로 직접 비동기 요청을 관리하는 예시예시: 예약 정보를 서버에서 가져와 렌더링하는 코드
기존 방식
import React, { useState, useEffect } from 'react'; const ReservationComponent = ({ reservationId }) => { const [reservation, setReservation] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { const fetchReservation = async () => { try { const response = await fetch(`/api/reservations/${reservationId}`); if (!response.ok) throw new Error('Failed to fetch'); const data = await response.json(); setReservation(data); } catch (err) { setError(err.message); } finally { setLoading(false); } }; fetchReservation(); }, [reservationId]); if (loading) return <p>Loading...</p>; if (error) return <p>Error: {error}</p>; return ( <div> <h1>Reservation for {reservation.customerName}</h1> <p>Room: {reservation.roomNumber}</p> </div> ); };
문제점
- 중복 코드
- 다른 컴포넌트에서도 비슷한 API 호출을 한다면 매번 같은 구조를 작성해야 함
- 로딩, 에러, 데이터 상태 등을 수동으로 관리해야 하므로 코드가 중복되고 복잡해짐
- 캐싱 없음
- 동일한 데이터가 필요한 여러 컴포넌트가 있을 때, 각 컴포넌트마다 중복 요청을 하게 됨
- 데이터 동기화 어려움
- 서버에서 데이터가 변경되었을 때, 이를 실시간으로 업데이트하기가 어려움
- 개발자가
useEffect를 이용해 데이터 갱신 로직을 직접 구현해야 함
- 에러 처리 비효율적
- 각 API 호출마다 try-catch와 loading 상태를 매번 설정해야 해서 코드가 길어짐
2. React Query로 개선된 코드
React Query를 사용하면 비슷한 기능을 훨씬 간결하게 구현할 수 있음
React Query 방식
import { useQuery } from 'react-query'; import axios from 'axios'; const fetchReservation = async (id) => { const { data } = await axios.get(`/api/reservations/${id}`); return data; }; const ReservationComponent = ({ reservationId }) => { const { data, isLoading, error } = useQuery(['reservation', reservationId], () => fetchReservation(reservationId), { staleTime: 1000 * 60 * 5 } // 5분 동안 캐시 유지 ); if (isLoading) return <p>Loading...</p>; if (error) return <p>Error: {error.message}</p>; return ( <div> <h1>Reservation for {data.customerName}</h1> <p>Room: {data.roomNumber}</p> </div> ); };
const { data, isLoading, error } = useQuery(['reservation', reservationId],첫 번째 인자는 쿼리 키로, ['reservation', reservationId] 형태로 배열을 사용하여 쿼리를 고유하게 식별
() => fetchReservation(reservationId),두 번째 인자는 데이터 fetching 함수로, 여기서는 예약 ID를 인자로 받아 fetchReservation(reservationId)를 호출
React Query의 장점
1. 코드가 더 간결함
- 로딩, 에러, 데이터 상태를 자동으로 관리함
useQuery하나로 데이터 요청과 상태 관리를 해결하므로 코드가 짧고 직관적임- 기존 코드에서는
useState와useEffect로 여러 상태를 수동으로 관리해야 했음
2. 자동 캐싱
- 동일한 데이터를 다시 요청할 때 캐시된 데이터를 먼저 보여주고, 필요 시 새로 갱신
- 예를 들어, 예약 목록과 예약 세부 정보 페이지가 같은 데이터를 요청할 경우 중복 호출을 피할 수 있음
3. 자동 리페칭 및 동기화
- 창을 다시 열거나 포커스할 때 데이터를 자동으로 리페칭
- 서버에서 데이터가 변경되면 자동으로 갱신되므로 실시간 동기화가 쉬워짐
4. 에러와 로딩 처리 간소화
- API 요청에 대한 에러와 로딩 상태를 자동으로 관리
- 여러 API 호출에서 중복된 try-catch와 상태 관리 코드가 사라짐
기존 코드와 React Query 코드 비교
기능 | 기존 React 코드 | React Query 코드 |
상태 관리 | useState와 useEffect를 직접 사용해야 함 | useQuery로 자동 관리 |
캐싱 | 수동 구현 필요 | 자동으로 캐싱 관리 |
리페칭 및 동기화 | 직접 구현 필요 | 창 포커스 시 자동 리페칭 |
코드 간결성 | 반복적인 상태 코드 작성 필요 | 훨씬 더 짧고 직관적 |
에러 및 로딩 처리 | 여러 try-catch와 로딩 상태 관리 필요 | 에러, 로딩 상태 자동 관리 |
성능 최적화 | 매번 새로 API 호출 | 캐싱된 데이터 재사용으로 성능 개선 |
React Query가 특히 유용한 이유
- 키오스크와 같은 복잡한 애플리케이션에서 여러 API를 호출할 때 코드 중복을 줄
- 중요한 서버 상태의 일관성을 보장합니다. 예를 들어, 예약 상태가 여러 화면에서 변경될 때 동기화를 쉽게 처리할 수 있음
- 실시간 리페칭과 캐싱을 통해 네트워크 요청 수를 줄이고, 성능 최적화가 가능함