본문 바로가기
개발/React

[RTK] RTK-Query?

by 그레이웅 2022. 11. 5. 17:37
반응형

RTK Query?

 

RTK Query는 데이터를 fetching, caching을 할 수 있는 툴이다. 웹에서 데이터를 가져오는 것을 간단하게 만들어 데이터 패치(가져오기)와 캐싱 로직을 작성할 필요가 없어지게 한다.

 

RTK-Query는 Redux-Toolkit 패키지에 포함되어있는 선택적인 추가 기능이다.

 

웹 애플리케이션은 일반적으로 서버에서 데이터를 가져오게되고, 데이터 업데이트 및 클라이언트의 캐시 된 데이터를 서버 데이터와 동기화된 상태로 유지해야 한다. 

 

RTK-Query는 Apollo Client, React Query, Urql 및 SWR과 같이 데이터 가져오기를 위한 선구적인 솔루션 제공 및 API 디자인에 고유한 접근 방식을 추가한다.

 

RTK Query 특징

 

- 데이터 패칭(가져오기) 및 캐싱 로직은 Redux Toolkit createSlicecreateAsyncThunk API를 기반으로 구축된다.

- Redux Toolkit은 UI에 구애받지 않기 때문에 RTK Query의 기능은 모든 UI 계층에서 사용할 수 있다.

- API 엔드포인트는 인수에서 쿼리 매개변수를 생성하고 캐싱을 위해 응답을 반환하는 방법을 포함하여 미리 정의된다.

- RTK 쿼리는 전체 데이터 패칭 프로세스를 캡슐화해 data와 isLoading필드를 컴포넌트에게 제공하고, 컴포넌트가 mount, unmount시 캐시된 데이터의 수명을 관리하는 React Hook를 생성할 수 있다.

- RTK 쿼리는 초기 데이터 패칭 후 웹 소켓 메시지를 통한 캐시 업데이트 스트리밍 같은 상황을 위해 "cache entry lifecycle"이라는 옵션을 제공한다.

- OpenAPI 및 GraphQL 스키마에서 API슬라이스 코드에대한 예시를 제공한다.

- RTK 쿼리는 타입스크립트로 만들어졌고, 완벽한 TS경험을 제공한다.

 

 

RTK-Query APIs

위에서 말했듯 RTK-Query는 RTK 패키지에 포함되어 있다. 아래 두 가지 중 하나를 통해 사용할 수 있다.

import { createApi } from '@reduxjs/toolkit/query'

// 리액트 엔트리 포인트를 명시하면 자동으로 정의된 엔드포인트의 훅을 생성합니다
import { createApi } from '@reduxjs/toolkit/query/react'

 

RTK Query의 API를 설명하자면

- createApi() : RTK 쿼리의 기능의 핵심이다. 데이터를 패치 및 변환하는 설정을 포함 엔드포인트들에서 어떻게 데이터를 패치하는지 정의할 수 있다. 대부분은 베이스 URL 하나당 하나의 API Slice를 사용한다. 

- fetchBaseQuery() : 간단한 요청을 위한 fetch의 wrapper이다. 대부분의 사용자에게 createApi의 baseQuery로 사용된다.

- <ApiProvider /> : 리덕스 스토어가 없다면 Provider로 사용가능하다.

- setupListeners() : refetchOnMount와 refetchOnReconnect를 사용하기 위한 유틸

 

 

번들 사이즈

RTK-Query는 고정된 크기를 앱의 번들 사이즈에 추가한다. Redux-Toolkit과 React-Redux위에서 빌드하기 때문에, 얼마나 사용하는지에 따라 사이즈가 달라진다. 

예상되는 min+gzip 번들 사이즈는 다음과 같다.

 

- RTK 사용 중이면 : RTK Query ~9kb, hooks ~2kb

- RTK를 사용 중이지 않는다면 : 

    - React 없음 : RTK+dependencies+RTK Query 17kb

    - React 있음 : 19kb + React-Redux(peer dependency)

 

엔드포인트는 endpoint내의 코드의 크기를 추가하며 일반적으로는 몇 바이트에 불과하다.

RTK-Query로 직접 작성한 데이터 패칭 로직을 제거하면 대부분의 애플리케이션 사이즈가 개선된다.

 

 

사용 방법

 

createAPI 정의

 

전형적으로 사용하는 방법은 먼저 createAPI를 정의한다.

import { createApi } from '@reduxjs/toolkit/query'

// 리액트 엔트리 포인트를 명시하면 자동으로 정의된 엔드포인트의 훅을 생성합니다
import { createApi } from '@reduxjs/toolkit/query/react'

 

APISlice 생성

 

createAPI 정의 이후 API Slice를 정의한다. 

서버의 baseUrl과 우리가 접근하고 싶은 엔드포인트의 리스트를 정의한다. 

import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
import { Pokemon } from './types'

// base URL과 엔드포인트들로 서비스 정의
export const pokemonApi = createApi({
  reducerPath: 'pokemonApi',
  baseQuery: fetchBaseQuery({ baseUrl: 'https://pokeapi.co/api/v2/' }),
  endpoints: (builder) => ({
    getPokemonByName: builder.query<Pokemon, string>({
      query: (name) => `pokemon/${name}`,
    }),
  }),
})

// 정의된 엔드포인트에서 자동으로 생성된 훅을 함수형 컴포넌트에서 사용하기 위해 export
export const { useGetPokemonByNameQuery } = pokemonApi

 

 

Store 설정

 

API slice를 리덕스 스토어에 추가해주어야 한다. 커스텀 미들웨어도 store에서 추가해줄 수 있다.

import { configureStore } from '@reduxjs/toolkit'
// Or from '@reduxjs/toolkit/query/react'
import { setupListeners } from '@reduxjs/toolkit/query'
import { pokemonApi } from './services/pokemon'

export const store = configureStore({
  reducer: {
    // 특정 top-level slice에서 생성된 리듀서를 추가
    [pokemonApi.reducerPath]: pokemonApi.reducer,
  },
  // 캐싱, 요청 취소, 폴링 등등 유용한 rtk-query의 기능들을 위한 api 미들웨어 추가
  middleware: (getDefaultMiddleware) =>
    getDefaultMiddleware().concat(pokemonApi.middleware),
})

// 옵셔널, refetchOnFocus/refetchOnReconnect 기능을 위해 필요함
// setupListeners 문서를 참고 - 커스텀을 위한 옵셔널 콜백을 2번째 인자로 받음
setupListeners(store.dispatch)

 

컴포넌트에서 Hooks 사용

 

API Slice에서 자동 생성된 hooks을 import 하고 필요한 파라미터와 함께 hooks 호출한다.

RTK Query는 자동으로 컴포넌트가 마운터 될 때 데이터를 패치, 파라미터가 바뀔 때 다시 패치를 하여 {data, isFetching} 값을 제공하고 컴포넌트를 리 렌더링 한다. 

import * as React from 'react'
import { useGetPokemonByNameQuery } from './services/pokemon'

export default function App() {
  // 자동으로 데이터를 패치하고 쿼리 값을 가져오는 쿼리 hook을 사용
  const { data, error, isLoading } = useGetPokemonByNameQuery('bulbasaur')
  // 각각의 hooks은 생성된 엔드포인트에서도 접근 가능함
  // const { data, error, isLoading } = pokemonApi.endpoints.getPokemonByName.useQuery('bulbasaur')
  
  // 데이터와 로딩 상태에 따라 UI를 렌더링
}

 

 


RTK-Query의 개요와 기본적인 API들을 알아보았다.

아직 기본적인 개념들이고 직접 사용해서 구현해보지 않아서 와닿지는 않는다

다음 포스팅에는 직접 실습해보면서, 알아봐야겠다.

 

반응형

댓글