
[컨퍼런스] 우아한테크세미나 | React Query와 상태관리
컨퍼런스 영상링크: React Query와 상태관리 :: 2월 우아한테크세미나
여러 회사들의 채용 공고를 찾아보면서, React Query에 대해 처음 알게 되었습니다. 많은 회사들이 React Query, SWR 등의 상태관리 라이브러리를 사용하는데, ‘왜 사용할까’라는 점에서 찾아보기 시작했습니다.
그러면서 React Query의 장점에 대해 알게 되었고 개인프로젝트에 사용해보면 좋겠다고 생각했습니다. 그러나 개인 프로젝트를 진행하면서 Recoil을 사용하는데 굳이 상태관리 라이브러리를 2가지 이상 사용해도 될까? 오버엔지니어링이 되지 않을까? 라는 걱정이 생겼습니다. 심지어 스택오버플로우에도 React Query를 사용하는데 굳이 Recoil, Redux과 같은 상태관리 라이브러리를 사용할 이유가 없다며 useContext를 사용하라는 글을 보기도 했습니다. 그러나 저에게는 공감이 되지 않았습니다.
이때 배민의 배민근님께서 작성하신 Store에서 비동기 통신분리하기를 읽고, Redux와 서버 상태관리(React Query) 라이브러리를 도입한 이유를 읽으면서 공감이 많이 됐었습니다. 그리고 실제로 사용경험도 매우 좋았었습니다. 마침 글을 작성하신 배민근님께서 우아한 테크세미나를 진행한다고 해서 참여하게 되었습니다.
아래의 글은 우아한 테크 세미나의 내용을 짧게 나마 정리한 글입니다.
상태관리의 분리
상태란
주어진 시간에 대해 시스템을 나타내는 것으로 언제든지 변결될 수 있으며, 문자열 배열 객체등의 혀애로 응용프로그램에 저장된 데이터를 의미합니다.
프론트엔드에게 지금까지의 상태란
UI/UX의 중요성과 프로턱트 규모가 커짐에 따라 FE가 관리하는 상태가 많아지게 되었습니다.
그간의 FE의 상태관리는 상태보다는 API 통신 코드에 더 가까울 정도로 주객전도된 상황이었습니다.
서버의 상태란
- Client에서 제어하거나 소유되지 않는 원격의 공간에서 관리되고 유지됨
- Fetching이나 Updating에 비동기 API가 필요함
- 유저가 모르는 사이 다른 사람들에 의해 변경될 수 있음
- 잠재적으로 out date 될 가능성을 지님
또한 FE에서 이러한 서버의 상태는 일종의 캐시라고 볼수 있습니다.
Owner ship에 의한 분리
그렇다면 상태는 어떻게 분리하면 좋을까요. 바로 Ownership에 따른 분기입니다.
Client State
- Client에서 소유하며 온전히 제어가능함
- 초기값 설정이나 조작에 제약 사항 없음
- 다른 사람들과 공유되지 않으며, Client 내에서 UI/UX흐름이나 사용자 인터렉션에 따라 변할 수 있음
- 항상 Client 내에서 최신 상태로 관리됨
Server State
- Client에서 제어하거나 소유되지 않은 원격의 공간에서 관리되고 유지됨
- Fetching/Updating에 비동기 API가 필요함
- 다른 사람들과 공유되는 것으로 사용자가 모르는 사이에 변경될 수 있음
- 신경 쓰지 않는다면 잠재적으로 “out of date”가 될 가능성을 지님
React Query
리액트 쿼리의 개요
React 애플리케이션에서 서버 상태를 가져오고, 캐싱하고, 동기화하고 업데이트하는 작업을 간단하게 만듭니다.
리액트 쿼리의 3가지 코어 컨샙
리액트 쿼리 코어 컨셉은 세 가지 요소를 나누어 설명할 수 있습니다.
-
Query: 일반적으로 데이터를 Fetch(Read)을 수행하는데 사용됩니다.
-
Mutation: Query와 달리 Mutation은 일반적으로 데이터를 생성/업데이트/삭제하거나 서버 부작용을 수행하는 데 사용됩니다.
-
Query Invalidation: fetch 된 데이터를 stale(오래된) 취급하여, 현재 랜더링 되고 있는 Queries들을 백그라운드에서 Refetch 합니다.
Query
React Query는 Query Key에 따라 query caching을 관리합니다.
React Query의 상태는 전역상태처럼 관리됩니다. 이는 QueryClient 내부적으로 Context를 사용하기 때문입니다.
설명중에서는 queries 파일 분리하는 것도 추천했습니다. 배달의 민족 주문 프론트팀의 경우에는 도메인 별로 나누어서 따로 관리한다고 했습니다.
Caching & Synchronization
React Query에서도 메모리 캐시를 적용할 수 있습니다.
- cacheTime: 메모리에 얼마만큼 있을건지 (해당시간 이후 GC에 의해 처리, default 5분)
- staleTime: 얼마의 시간이 흐른 후에 데이터를 stale 취급할 것인지 (default 0)
Default 값은 무엇인가?
-
staleTime:
- default: 0
- Quries에서 cached data는 언제나 stale 취급
-
refetchOnMount/refetchOnWindowFocus/refetchOnReconnect
- default: true
- 각 시점에서 data가 stale이라면 항상 refetch
-
cacheTime
- default: 60 _ 5 _ 1000
- inActive Query들은 5분 뒤 GC에 의해 처리
일반적으로 QueryCache와 직접 상호 작용하지 않고 대신 QueryClient를 통해 특정 캐시에 접근합니다.
4. 끝맺음
글을 작성하셨던 배민근님께서 직접 설명을 해주니니까 이해하는데 도움이 많이 되었던 것 같습니다. 그리고 React Query를 사용해봤지만, 정말 전체 기능의 일부밖에 활용하지 못한 부분도 있다는 것을 느꼈습니다.
사실 가장 궁금했던 부분은, react query를 사용하면서 Suspense를 어떤 방식으로 사용하는지 궁금했습니다. 이에 ErrorBoundary, Suspense를 사용하지 않고 컴포넌트 내부에서 UI에 대한 로직을 명시한다고 했습니다. 아무래도 결제와 관련된 서비스이다보니 안정성이 우선이라, 실험단계에 있는 기능을 사용하는 것에 한계가 있기 때문이라고 하셨습니다. 아무래도 각각의 에러상황에 대해 개인적으로 고민이 필요할 것 같습니다.