React-Query는 React Application에서 서버 상태를 관리하는 데 도움을 주는 라이러리 입니다.
REST API나 GraphQL API로부터 데이터를 쉽게 가져올 수 있습니다.
가져온 데이터를 자동으로 캐싱하여, 동일한 요청에 대해 네트워크 재사용을 줄여 빠르게 응답할 수 있게 합니다.
데이터가 변경될 때 자동으로 다시 가져오거나, 특정 interval 마다 데이터를 업데이트 합니다. 이를 통해 오래된 데이터의 상태를 파악하여 업데이트합니다.
가비지 컬렉션을 통해 서버 쪽 데이터 메모리를 관리해 줍니다.
Server에서 가져온 데이터와 Client에서 관리하는 상태를 분리하여, 더 나은 상태 관리를 제공합니다.
Redux를 통해 애플리케이션의 상태를 관리하고, API 통신을 수항하고 비동기 데이터를 관리했습니다.
설정 및 Boilerplate : Redux 스토어를 설정하고, Reducer를 정의하는 데 많은 코드가 필요합니다.
이는 Boilerplate라고 하는 불필요하고 반복되는 코드입니다.
규격화 방식의 부재 : Redux는 API 통신 및 비동기 상태 관리를 위한 라이브러리가 아니라, 애플리케이션 상태 관리를 위한 라이브러리입니다.
API 로딩을 따로 관리하건, isLoading: boolean; 이나
statue: 'IDLE' | 'LOADING' | 'SUCCESS' | 'ERROR';처럼 따로 추가를 해야합니다.
데이터 요청의 분산 : 데이터 요청 로직이 Reducer 혹은 Action 생성자에 분산되어 있어 가독성이 떨어집니다.
MobX는 JavaScript 애플리케이션의 상태 관리 라이브러리입니다. 상태 관리의 복잡성을 줄이고, 상태의 변화를 쉽게 추적할 수 있도록 설계 되었습니다.
MobX는 Redux에 비해 객체 지향적입니다.
서버 상태 관리 최적화 : MobX는 서버 상태 관리를 위해 추가적 로직이 필요하지만, React-Query는 아닙니다.
자동 캐싱 및 Re-Fetching : MobX는 React-Query에서 가능한 데이터 요청 자동 캐싱 및 데이터 변경 시 Re-Fetching을 수동으로 구현해야 합니다.
비동기 로직 간소화 : MobX에 비해 React-Query는 비동기 요청을 위한 훅 useQuery, useMutation.. 을 제공해 비동기 로직을 간단하게 처리할 수 있습니다.
싱태와 UI 분리 : MobX는 상태가 UI와 밀접하게 연결되어 있지만, React-Query는 명확히 구분되어 있습니다.
$ npm install @tanstack/react-query
QueryClientProvider : React 애플리케이션 컴포넌트 트리에 QueryClient 공급하여 모든 컴포넌트가 QueryClient에 접근할 수 있도록 함
QueryClient : 서버 상태를 관리하고, 데이터 캐싱 및 Re-Fetching 등 쿼리의 전반적인 동작 설정하는 객체
QueryClient 전달 : QueryClientProvider로 감싸진 모든 하위 컴포넌트는 useQuery, useMutation 등 훅을 통해 QueryClient에 접근합니다.import React from 'react';
import ReactDOM from 'react-dom';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import App from './App';
const queryClient = new QueryClient();
ReactDOM.render(
<QueryClientProvider client={queryClient}>
<App />
</QueryClientProvider>,
document.getElementById('root')
);
useQuery 훅을 통해 데이터를 가져옵니다.
import React from 'react';
import { useQuery } from '@tanstack/react-query';
const fetchTodos = async () => {
const response = await fetch('https://example.com/todos');
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
};
const TodoList = () => {
const { data, error, isLoading } = useQuery(['todos'], fetchTodos);
if (isLoading) {
return <div>Loading...</div>;
}
if (error) {
return <div>Error: {error.message}</div>;
}
return (
<ul>
{data.map(todo => (
<li key={todo.id}>{todo.title}</li>
))}
</ul>
);
};
export default TodoList;
데이터 추가/수정/삭제 경우 useMutation 훅을 사용합니다.
이 후 쿼리 무효화를 통해 데이터의 일관성과 최신성을 유지합니다.
import React from 'react';
import { useMutation, useQueryClient } from '@tanstack/react-query';
const addTodo = async (newTodo) => {
const response = await fetch('https://jsonplaceholder.typicode.com/todos', {
method: 'POST',
body: JSON.stringify(newTodo),
headers: {
'Content-Type': 'application/json',
},
});
return response.json();
};
const TodoForm = () => {
const queryClient = useQueryClient();
const mutation = useMutation(addTodo, {
onSuccess: () => {
// 쿼리 무효화
queryClient.invalidateQueries(['todos']);
},
});
const handleSubmit = (event) => {
event.preventDefault();
const newTodo = { title: event.target.elements.todo.value };
mutation.mutate(newTodo);
};
return (
<form onSubmit={handleSubmit}>
<input name="todo" required />
<button type="submit">Add Todo</button>
</form>
);
};
export default TodoForm;
Apoll Client는 주로 GraphQL API와의 통신을 위한 라이브러리로, GraphQL 쿼리와 변형을 쉽게 사용할 수 있지만,
React-Query는 REST API와 GraphQL API 모두 데이터를 가져오고 관리하는 데 최적화되어 있습니다.
SWR은 stale-while-revalidate 전략을 기반으로 데이터를 가져오는 데 중점을 두고 직관적인 API를 제공하고, 캐싱과 Re-Fetching에 최적화 되어 있습니다.
React-Query는 서버 상태 관리를 위한 라이브러리로, 데이터 Fetching, 캐싱, 동기화, 오류 처리 등 기능을 지공하고, 비동기 데이터 요청을 간편하게 처리할 수 있습니다.
결론은 KakaoPay 프론트엔드 개발자들이 React-Query를 선택한 이유 세 줄 요약을 인용하겠습니다.
React-Query는 React Application 서버 상태를 불러오고, 캐싱하며, 지속적으로 동기화하고 업데이트하는 작업을 도와주는 라이브러리입니다.
React Component 내부에서 간단하고 직관적인 API를 사용 가능하며, 이는 복잡한 다른 데이터 Fetching 방식과는 다릅니다.
React-Query에서 제공하는 캐싱, Window Focus Re-Fetching 등 다양한 기능을 통해 API 요청의 핵심 로직에 집중할 수 있습니다.