리액트 쿼리를 처음 접하고, 정말 편리하고 멋진 도구라는 생각이 들었다.
좀 더 잘 써보고 싶어서 여러 문서를 찾아 읽으며 개념을 정리했고, 정리한 내용을 하나씩 남겨보려고 한다.
새로운 기술 스택을 공부할 때는 역시 공식 문서가 국룰이라고 생각한다. 로고가 묘하게 징그럽다.
공식 홈페이지의 메인에 들어가면 아래와 같은 화면을 볼 수 있다.
v3에서는 React Query 라는 명칭을 사용하였으나, v4로 넘어오면서 React 뿐만 아니라 SolidJS, Vue, Svelte 까지 지원하기 위해 TanStack Query로 명칭을 변경한 듯 하다.
밑줄까지 쳐서 TS와 JS, React 등을 위한 강력한 비동기 상태 관리 도구라고 자신을 소개하고 있는 것을 확인할 수 있다.
이 문구가 와닿지 않는다면 Overview를 살펴보자.
소개글에 나와있는 것처럼 리액트 쿼리는 단순히 리액트를 위해 서버 데이터를 패칭해주는 라이브러리가 아니다.
서버 데이터 패칭(fetching)과 캐싱(caching), 동기화(synchronizing) 및 업데이트(updating) 작업을 편하게 만들어 주는 라이브러리라고 생각하면 된다.
fetching, caching, synchronizing, updating의 개념
나와 친구들의 프로필이 존재하고, 할 일 리스트를 공유하는 앱이 있다고 해보자.
그러면 각각의 개념에 대해 다음과 같이 예시로 들어볼 수 있다.1. fetching: 나의/친구의 할 일을 서버로부터 가져오기
2. caching: 서버로부터 받아온 나의 일 정보를 저장해두고, 3(n)초 이내에 접근 시 서버에 다시 요청하지 않고 저장해둔 정보를 그대로 사용하기
3. synchronizing: 친구가 할 일을 완료 처리했을 때 내가 보고 있는 화면에 반영하기
4. updating: 할 일 삭제/완료
리액트 쿼리가 왜 등장하게 됐는지 이해한다면, "왜 리액트 쿼리를 쓰는가"에 대한 의문을 좀 더 잘 해소할 수 있다. 리액트 쿼리의 등장 배경을 설명하고자 한다면 앱 내에서 클라이언트 상태와 서버 상태 간 분리의 필요성에 대한 언급을 빼놓을 수 없다.
공식 문서에서 밝히는 리액트 쿼리의 Motivation을 살펴보며 함께 얘기해보자.
리액트는 서버에서 데이터를 가져오거나, 업데이트하는 명확한 방법을 제공하지 않기 때문에, 개발자들이 직접 이를 처리해주어야 한다.
일반적으로 컴포넌트에서 hook을 사용하여 데이터를 가져와 상태를 관리하거나, 전역 상태 관리 라이브러리를 통해 store에 비동기 데이터를 저장하고 앱의 여기저기에서 가져다가 사용한다.
투두리스트 앱을 예시로 전자의 방식을 코드로 작성해보자.
const TodoList = () => {
const [todos, setTodos] = useState([]);
// useEffect hook을 사용해 todos 데이터를 가져와 관리
useEffect(() => {
axios
.get('/todos')
.then(({ data }) => { setTodos(data.todos) });
}, []);
// todos 데이터를 업데이트하는 코드
const onRemove = (id) => {
axios
.delete(`/todo/${id}`)
.then(() => {
const newTodos = todos.filter((todo) => todo.id !== id);
setTodos(newTodos);
}
}
...
}
서버에 저장되어 있는 할 일 리스트를 불러오기 위해 useEffect 훅에서 api 요청을 보냈고, 받아온 데이터를 useState 훅으로 선언한 todos 상태에 저장했으며, 할 일을 제거하기 위해 서버에 api 요청을 보내고, 갱신된 데이터를 todos 상태에 저장해 주었다.
서버에서 데이터를 가져오고, 이를 업데이트하기 위해 useEffect 훅에서 api 요청을 보내고, 받아온 데이터를 useState 훅으로 선언한 todos 상태에 저장하는 작업은 리액트에서 제공하는 훅을 우리 개발자의 의도에 맞게끔 활용을 한 것일 뿐, 서버 데이터를 관리하기 위해 제공되는 도구는 아니다.
전역 상태 관리 라이브러리를 통해 store에 비동기 데이터를 저장하고 앱의 여기저기에서 가져다가 사용하는 방식도 서버에서 받아오는 데이터인 서버 상태를 관리하기에 쉽지 않다.
왜냐?
서버 상태는 다음과 같은 특징을 갖기 때문이다.
이러한 서버 상태를 store에서 관리하게 되면, 여러가지 챌린지에 부딪히게 된다.
리액트 쿼리는 위와 같은 챌린지들을 아주 간단하게 해결해줄 뿐만 아니라,
기존 라이브러리에 비해 상당히 간결한 코드로 서버 상태를 관리하게 해주고, 이를 통해 훨씬 더 유연한 앱을 만들 수 있게 해준다.
유저들에게는 깔끔한 UX를 제공하면서!
그렇다면 리액트 쿼리가 어떻게 이러한 챌린지를 해결하고 있는지, 다음편에 작성해보려고 한다.