eatthefrog
React Query 본문
useEffect VS React Query
조건: 사용자가 식당 예약 목록을 보고 있다. 이때 최신 예약 데이터를 서버에서 가져와야 하며, 예약 목록이 실시간으로 업데이트되도록 하고 싶다.
1. useEffect로 구현하는 방법
import { useEffect, useState } from 'react';
function ReservationList() {
const [reservations, setReservations] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
async function fetchReservations() {
setLoading(true);
try {
const response = await fetch('https://api.example.com/reservations');
if (!response.ok) throw new Error('Failed to fetch reservations');
const data = await response.json();
setReservations(data);
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
}
}
fetchReservations();
}, []);
if (loading) return <p>Loading...</p>;
if (error) return <p>Error: {error}</p>;
return (
<ul>
{reservations.map((res) => (
<li key={res.id}>{res.name}</li>
))}
</ul>
);
}
문제점
- 로딩, 에러, 데이터 상태 관리를 직접 구현해야 함.
- 캐싱 없음: 동일한 데이터를 여러 번 요청.
- 자동 리페치 지원 부족: 사용자가 데이터를 갱신하려면 수동으로 새로 고침 필요.
2. React Query로 구현하는 방법
import { useQuery } from '@tanstack/react-query';
async function fetchReservations() {
const response = await fetch('https://api.example.com/reservations');
if (!response.ok) throw new Error('Failed to fetch reservations');
return response.json();
}
function ReservationList() {
const { data: reservations, error, isLoading } = useQuery(['reservations'], fetchReservations);
if (isLoading) return <p>Loading...</p>;
if (error) return <p>Error: {error.message}</p>;
return (
<ul>
{reservations.map((res) => (
<li key={res.id}>{res.name}</li>
))}
</ul>
);
}
React Query의 장점
- 로딩, 에러, 데이터 상태 관리 자동화: 상태 변수를 직접 관리할 필요 없음.
- 자동 캐싱: 동일한 데이터를 다시 요청하지 않음.
- 자동 리페치: 데이터가 변경되면 자동으로 최신화.
- 백그라운드 데이터 동기화: 사용자가 화면을 떠나거나 다시 돌아올 때 데이터 갱신 가능.

정리
| 기능 | useEffect + useState | React Query |
| 상태 관리 | 수동 관리 (loading, error, data) | 자동 관리 (isLoading, error, data) |
| 캐싱 | 없음 | 자동 캐싱 |
| 자동 리페치 | 직접 새로 고침 함수 구현 필요 | 자동 리페치 제공 |
| 백그라운드 업데이트 | 직접 구현해야 함 | 자동화 가능 |
| 코드 간결성 | 많은 보일러플레이트 코드 필요 | 더 적은 코드로 동일한 기능 |
언제 사용해야하는가?
| 사용 상황 | useEffect + useState | React Query |
| DOM 조작, 타이머, 이벤트 핸들링 | ✅ | ❌ |
| 간단한 로컬 상태 관리 | ✅ | ❌ |
| 서버에서 데이터를 가져오고 관리 | ❌ | ✅ |
| 캐시 및 리페치가 필요 | ❌ | ✅ |
| 자동 로딩 및 에러 상태 관리 | ❌ | ✅ |
| 대규모 프로젝트 또는 데이터 집약적 애플리케이션 | ❌ | ✅ |
React Query 사용 방법
- 설치 : npm install @tanstack/react-query
- 주요 기능 요약
- useQuery를 사용하여 데이터를 가져옴.
- data는 캐시된 데이터를 나타냄.
- isLoading은 로딩 상태를 관리함.
- error는 에러 상태를 처리함.
import { useQuery } from '@tanstack/react-query';
async function fetchUser() {
const response = await fetch('https://api.example.com/user');
if (!response.ok) throw new Error('Network response was not ok');
return response.json();
}
function UserComponent() {
const { data, error, isLoading } = useQuery(['user'], fetchUser);
if (isLoading) return <p>Loading...</p>;
if (error) return <p>Error: {error.message}</p>;
return (
<div>
<h1>{data.name}</h1>
<p>{data.email}</p>
</div>
);
}
추가 팁: React Native 환경에서 React Query 사용
- 네트워크 연결 상태 관리: React Query는 네트워크 상태 변화를 감지하여 연결이 복구되면 자동으로 데이터를 리페칭한다. React Native에서는 NetInfo 라이브러리와 통합할 수 있다.
- 리스트 관리: 무한 스크롤이나 페이징 데이터를 가져오는 작업에 React Query의 useInfiniteQuery를 활용할 수 있다.