-
[React] React-Query와 상태관리 (feat.우아한 테크 세미나) - 1Today's/DevelopStory 2023. 6. 30. 10:43
React혹은 React-Native 프로젝트를 진행하면서 무심코 사용해왔던 React-Query에 대해 한번 정리하고자 한다.
유튜브 채널 "우아한 테크"의 2022년 2월에 올라온 영상, React-Query와 상태관리 편을 시청하면서 정리했다.
서론
상태란 무엇인가?
- 상태(State)는 주어진 시간에 대해 시스템을 나타내는 것. 언제든지 변경될 수 있다.
- UI/UX의 중요성이 부각되면서 관리해야되는 상태가 많아졌다.
- Props Drilling 이슈로 인해 Redux, Mobx 같은 라이브러리를 활용하기도 한다.
상태관리 영역의 확장
- 서버값을 저장하는 것까지 개념이 확장됨
- 기존 redux와 같은 전역상태관리 라이브러리의 store에 API 통신 관련 코드가 포함되기 시작
- isError, isFetching 등의 API 관련 상태가 반복되고 이러한 구조의 통신코드가 계속 반복됨
- 결론적으로 전역상태관리와 관련된 코드가 비대해지고 가독성이 떨어짐
서버에서 받아야하는 상태들의 특성
- Client에서 제어하거나 소유되지 않은 원격의 공간에서 관리되고 유지됨
- Fetching이나 Updating에 비동기 API가 필요함
- 다른 사람들과 공유되는 것으로 사용자가 모르는 사이에 변경될 수 있음
- 신경 쓰지 않는다면 잠재적으로 “out of date”가 될 가능성을 지님
- 사실상 프론트에서 저장하고 있는 상태들은 일종의 캐시 개념
본론
서버가 소유권을 가지는 Data, 즉 서버의 상태를 관리하는 라이브러리가 필요하다 → React-Query
React-Query란?
- 서버상태-데이터가져오기(fetching), 캐시(caching), 동기화(synchronizing), 업데이트(updating)-를 관리해주는 라이브러리이다.
- 유저들의 입맛대로 구성이 가능한 zero-config 베이스로 되어있다.
Core 컨셉 3가지 (Fetching, Updating)
- Queries : CRUD의 Reading용으로 사용, 즉 Fetching 용이다.
- Mutations : CRUD의 Create/Update/Delete 모두에 사용된다.
- QueryInvalidation : 백그라운드에서 refetching 하는 용도.
Queries
import { useQuery} from 'react-query' function App () { const info = useQuery('todos', fetchTodoList) } // 'todos' : queryKey // 'fetchTodoList : queryFunction (API 통신 함수)
- Query Key
- React Query는 Query Key에 따라 query caching을 관리한다.
- string 형태와 array 형태로 관리 할 수 있다.
- array 형태는 pagination 등의 다양한 옵션을 줄때 사용한다. code convention에 따라 주로 array형태로 쓰기도 한다.
- Query Function
- Promise를 반환하는 함수
- 데이터 resolve 혹은 error를 throw
- userQuery가 반환하는 것들
- data: 마지막으로 성공한 resolve된 데이터 (Response)
- error: 에러가 발생했을때 리턴되는 객체
- isFetching: Request가 in-flight 상태
- status, isLoading, isSuccess, isLoading 등 → 현재 query의 상태
- refetch: 해당 query refetch하는 함수 제공
- remove: 해당 query cache에서 지우는 함수 제공
- useQuery의 옵션들
- onSuccess, onError, onSettled: 성공/실패/완료 시 실행할 SideEffect
- enabled: 자동으로 query를 실행시킬지 여부
- retry: query동작 실패 시, 자동으로 retry 할지 결정하는 옵션
- select: 성공 시 가져온 data 가공해서 전달
- keepPreviousData: 새로운 데이터 fetching 시 이전 데이터 유지 여부
- refetchInterval: 주기적으로 refetch
💡 queries 파일로 분리하여 관리하는 것을 추천한다. 컴포넌트에 useQuery 구문을 작성하면 코드가 비대해질 수 있기 때문
Mutations
const mutation = useMutation(newTodo => { return axios.post('/todos', newTodo) })
- useMutation이 반환하는 것들
- mutate: mutation을 실행하는 함수
- mutateAsync: mutate와 비슷하나 Promise를 반환한다.
- reset: mutation 내부 상태 clean
- useMutation의 옵션들
- onMutate: 본격적인 Mutation 동작 전에 먼저 동작하는 함수 Optimistic update 적용에 유용함
- Optimistic update란? 서버의 요청이 성공할 것을 가정하고 화면을 업데이트 하는 것을 뜻함. (예: sns의 ‘좋아요’버튼을 누르면 서버의 반환값을 기다리지 않고 화면이 갱신됨. 단, 실패 시에는 롤백가능하다.)
- onMutate: 본격적인 Mutation 동작 전에 먼저 동작하는 함수 Optimistic update 적용에 유용함
QueryInvalidation
const queryClient = useQueryClient() queryClient.invalidateQueries('todos')
- invalidateQueries() 함수 내부의 QueryKey를 입력하여 사용
- 해당 key를 가진 query는 stale(신선하지 않은)취급되고, 현재 rendering 되고 있는 query들은 백그라운드에서 refetching된다.
캐싱(caching)과 동기화(synchronizing)에 대한 내용은 2부로 나누어 작성함.
'Today's > DevelopStory' 카테고리의 다른 글
[React] Dynamic Import 를 조금 더 동적으로 활용할 순 없을까? (0) 2024.09.04 [ReactNative] Build 환경 분리하기 (feat. Codepush) (0) 2023.03.28 [ReactNative] 숫자 3자리마다 콤마(",") 삽입하기 (0) 2023.03.24 [ReactNative] Appcenter Codepush 연동하기 (0) 2023.03.24 [Compose] LaunchedEffect와 DisposableEffect 그리고 React의 useEffect와 유사점 (1) 2023.02.23