1. React Query란?
(1) 개념
리액트 쿼리란?
React Query는 React 애플리케이션에서 데이터를 관리하기 위한 JavaScript 라이브러리입니다. 이 라이브러리는 서버에서 데이터를 가져오고 업데이트하는 등의 비동기 작업을 쉽게 다룰 수 있도록 도와줍니다. React Query는 상태 관리, 캐싱, 재시도, 인터벌 업데이트 등 다양한 기능을 제공하여 애플리케이션의 성능을 최적화하고 사용자 경험을 향상시킬 수 있도록 도와줍니다.
(2) 기존 미들웨어의 한계
다른 서버와의 API 통신과 비동기 데이터 관리를 위해 Redux-thunk, Redux-Saga 등 미들웨어를 채택해서 사용할 수 있지만 다음과 같은 문제가 있습니다.
- 보일러 플레이트 : 코드량이 너무 많아요.
- 규격화 문제 : Redux가 비동기 데이터 관리를 위한 전문 라이브러리가 아님(규격화 문제)
(3) 리액트 쿼리의 강점 : 너무 쉽고, 책임에서 자유롭죠
- 보일러 플레이트 만들다가 오류날 일이 없어요!
- 사용방법이 기존 thunk 대비 너무 쉽구요, 직관적이에요.
2. 주요 키워드
(1) Query
어떤 데이터에 대한 요청을 의미해요!
axios의 경우 get 요청과 비슷합니다.
const response = await axios.get(’http://localhost:3000/todos’)
(2) Mutation
어떤 데이터를 변경하는 거에요.
어떤 데이터라 함은, 데이터 그룹 그 자체를 의미한답니다.
바꾼다는 것은 추가, 수정, 삭제를 의미해요. CRUD 중, CUD에 해당해요. (Create, Update, Delete)
axios의 경우 post, put, patch, delete 요청과 비슷합니다.
axios.post(’http://localhost:3000/todos’., newTodo);
axios.patch(`http://localhost:3000/todos/${id}`, {isDone: true});
(3) Query Invalidation
위에서 보았던 Query를 invalidation. 즉, 무효화 시킨다는 의미입니다.
무효화 시킨다는 것이 무슨 의미일까요?
기존에 가져온 Query는 서버 데이터이기 때문에, 언제든지 변경이 있을 수 있어요. 그렇기 때문에 ‘최신 상태가 아닐 수’ 있습니다. 그런 경우, 기존의 쿼리를 무효화 시킨 후 최신화 시켜야 하겠죠.
이런 과정을 React Query에서는 알아서 해준답니다. 그 유용한 기능이 바로 Query Invalidation이에요.
3. 구현해보기
우선 react-qeury를 사용하기 위해 아래 명령어로 react-query를 설치해주세요.
yarn add react-query
App.jsx
import React from "react";
import Router from "./shared/Router";
import { QueryClient, QueryClientProvider } from "react-query";
const queryClient = useQueryClient();
const App = () => {
return (
<QueryClientProvider client={queryClient}>
<Router />;
</QueryClientProvider>
);
};
export default App;
App.jsx에서는 다음과 같이 react-query에서 제공하는 QueryClient API를 설정해 주세요.
QueryClientProvider : 데이터를 읽어오는 기능(QueryClient)을 애플리케이션 전체에 주입하도록 하는 API
서버로는 json server를 사용하도록 하겠습니다.
json server 설정이 안되셨다면, 먼저 설정을 하고 와주세요! axios도 설치 꼭 해주세요.
yarn add axios
useQuery를 이용하여 조회기능을 구현해볼게요. 먼저 src > api 폴더를 만들어주시고 그 아래에 todos 관련 api를 관리할 파일을 만들겠습니다.
src > api > todos.js
import axios from "axios";
// 모든 todos를 가져오는 api
const getTodos = async () => {
const response = await axios.get("http://localhost:3000/todos");
return response;
};
export { getTodos };
TodoList 컴포넌트의 코드도 변경해주겠습니다.
Todolist.jsx
import React from "react";
import { StyledDiv, StyledTodoListHeader, StyledTodoListBox } from "./styles";
import Todo from "../Todo";
import { __getTodosThunk } from "../../modules/todosSlice";
import { getTodos } from "../../../api/todos";
import { useQuery } from "react-query";
function TodoList({ isActive }) {
const { isLoading, isError, data } = useQuery("todos", getTodos);
if (isLoading) {
return <p>로딩중입니다....!</p>;
}
if (isError) {
return <p>오류가 발생하였습니다...!</p>;
}
return (
<StyledDiv>
<StyledTodoListHeader>
{isActive ? "해야 할 일 ⛱" : "완료한 일 ✅"}
</StyledTodoListHeader>
<StyledTodoListBox>
{data
.filter((item) => item.isDone === !isActive)
.map((item) => {
return <Todo key={item.id} todo={item} isActive={isActive} />;
})}
</StyledTodoListBox>
</StyledDiv>
);
}
export default TodoList;
const { isLoading, isError, data } = useQuery("todos", getTodos);
이 부분이 React Query가 가지고 있는 큰 장점이라 할 수 있어요. Thunk를 이용하면 state에서 isLoading, isError등을 개발자가 직접 만들어줬어야 했죠.
React Query는 서버 데이터를 위한 표준을 이미 제시하고 있기 때문에 개발자들 마다의 특성에 따라 바뀔 염려가 없습니다.
return 문에 도착하기 전에 isLoading 또는 isError에 따라 별도의 처리를 해주기 때문에 대기상태 처리 / 오류 처리에 대한 부분도 아주 쉽게 해결이 되었어요!
(2) 추가 기능 구현
src > api > todos.js
import axios from "axios";
// 공통으로 뺐어요(물론 .env를 쓰는게 더 바람직해요)
const SERVER_URI = "http://localhost:4000";
const getTodos = async () => {
const response = await axios.get(`${SERVER_URI}/todos`);
return response.data;
};
const addTodo = async (newTodo) => {
await axios.post(`${SERVER_URI}/todos`, newTodo);
};
export { getTodos, addTodo };
Input.jsx
...
import { addTodo } from "../../../api/todos";
import { QueryClient, useMutation } from "react-query";
...
function Input() {
...
const queryClient = new QueryClient();
const mutation = useMutation(addTodo, {
onSuccess: () => {
// Invalidate and refresh
// 이렇게 하면, todos라는 이름으로 만들었던 query를
// invalidate 할 수 있어요.
queryClient.invalidateQueries("todos");
},
});
[invalidate의 과정]
Input.jsx에서 값 입력으로 인해 서버 데이터가 변경됨
→ onSuccess가 일어나면 기존의 Query인 “todos”는 무효화
→ 새로운 데이터를 가져와서 “todos”를 최신화시킴
→ TodoList.jsx를 갱신함
따라서 계속해서 리액트 앱은 최신 상태의 서버 데이터를 유지할 수 있게 되는거에요.
지금까지 React Query 에 대해 알아보았습니다. React Query는 애플리케이션의 상태 관리를 단순화하고 비동기 데이터 로딩을 간편하게 다룰 수 있도록 도와주는 강력한 라이브러리 중 하나로 평가되고 있습니다. 여러분들도 한번씩 사용해보셨으면 좋겠습니다.
'React' 카테고리의 다른 글
Next.js 와 React.js 의 차이 (1) | 2024.03.04 |
---|---|
React - Throttling & Debouncing (0) | 2023.12.09 |
React - Custom Hooks (0) | 2023.12.09 |
React - Redux Thunk 자세히 다뤄보기 (1) | 2023.12.03 |
React - Thunk(feat. Redux)란? (1) | 2023.11.30 |