RTK Query(Query 편)

임효진·2023년 2월 19일
0

RTK 쿼리란?

  • RTK Query는 어플리케이션의 데이터를 로딩하는 케이스를 보다 쉽게 구현하는 진보된
    패칭, 캐싱 툴이다. 데이터를 가져오는 단순한 상황을 간단하게 만들어서 Data fetching과
    caching 로직을 스스로 작성할 필요가 없다.

특징

  • 스피너 UI의 로딩 상태관리
  • 동일한 데이터에 대한 중복 요청 방지
  • UI가 느리지 않도록 업데이트 최적화
  • UI와 상호작용할 때 캐시 상태 관리

기본 예시

// createApi를 import하기위해 React 엔트리 포인트 사용
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
  • RTK Query는 일반적으로 전체 API를 한 곳에 정의한다.
  • RTK Query는 어떠한 컴포넌트든 같은 쿼리를 구독하면 전부 갱신된다.
  • 데이터 패칭과 캐싱 로직은 Redux Toolkit의 createSlice와 createAsyncThunk API 위에서 동작한다.
  • Redux Toolkit은 UI 독립적이기 때문에 RTK Query의 기능들은 모든 UI 계층에서 사용할 수 있다.
  • API 엔드포인트는 인자로부터 쿼리 파리미터를 생성하고 캐싱을 위해 응답을 변환하는 방법을 포함해서 미리 정의된다.
  • RTK Query는 데이터 패칭 프로세스를 캡슐화해서 data와 isLoading필드를 컴포넌트에게 제공하고, 컴포넌트가 mount, unmount시 캐시 된 데이터의 라이프타임을 관리하는 React hook을 제공한다.
  • RTK Query는 초기 데이터를 패칭후 웹소켓 메시지를 통해 캐시 업데이트 스트리밍 같은 상황을 위한 "cache entry lifecycle"이라는 옵션을 제공한다.
  • RTK Query는 완전히 타입스크립트로 작성되었으며, 완벽한 타입스크립트 경험을 제공한다.

Query

  • 보통 읽기 요청에만 사용하는 것을 권장한다. 서버의 데이터를 변경하거나 캐시를 무효화할때는 Mutation을 사용한다.
  • RTK Query는 axios같은 라이브러리같이 요청 헤더와 응답 파싱을 자동으로 처리하는 가벼운 fetch 래퍼인 fetchBaseQuery를 제공한다.
  • 쿼리 엔드포인트는 createApi의 endpoints에서 builder.query() 메소드를 사용해서 정의한다.
    쿼리 엔드포인트는 URL(URL 쿼리 파라미터 포함)을 반환하는 query 콜백이나 임의의 비동기 로직을 수행하고 결과를 반환하는 queryFn 콜백을 정의해야 한다.
  • query 콜백에서 URL을 생성할 때 추가적인 데이터가 필요하다면 하나의 매개변수를 작성해야 한다. 만약 여러 개의 매개변수를 전달해야 한다면 하나의 객체로 만들어서 전달해야 한다.

예제

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

const api = createApi({
  baseQuery: fetchBaseQuery({
    baseUrl: '/',
  }),
  tagTypes: ['Post'],
  endpoints: (build) => ({
    getPost: build.query<Post, number>({
      // 노트: `queryFn`을 `query`자리에 사용할 수도 있습니다. 
      query: (id) => ({ url: `post/${id}` }),
      // data를 가져와서 hook이나 selector에서 중첩된 프로퍼티를 방지합니다. 
      transformResponse: (response: { data: Post }) => response.data,
      providesTags: (result, error, id) => [{ type: 'Post', id }],
      // 2번째 파라미터는 구조분해된 `QueryLifecycleApi`입니다. 
      async onQueryStarted(
        arg,
        {
          dispatch,
          getState,
          extra,
          requestId,
          queryFulfilled,
          getCacheEntry,
          updateCachedData,
        }
      ) {},
      // 2번째 파라미터는 구조분해된 `QueryCacheLifecycleApi`입니다. 
      async onCacheEntryAdded(
        arg,
        {
          dispatch,
          getState,
          extra,
          requestId,
          cacheEntryRemoved,
          cacheDataLoaded,
          getCacheEntry,
          updateCachedData,
        }
      ) {},
    }),
  }),
})

리액트 hooks과 함께 쿼리 사용하기

리액트 hooks를 사용한다면 RTK Query는 추가적인 기능을 제공한다. 가장 큰 이점은 hooks을 통해 백그라운드 패칭에 대한 불리언 값을 손쉽게 사용할 수 있다.
hooks는 서비스의 endpoint에서 자동으로 생성된다.
getPost: builder.query() 엔드포인트는 useGetPostQuery hook을 생성한다.

Hook의 종류

다음과 같은 5개의 쿼리와 관련된 hooks이 있다:

useQuery

useQuerySubscription과 useQueryState를 구성하는 기본 hook. 엔드포인트에서 자동으로 데이터를 패치하고, 캐시된 데이터를 컴포넌트에 구독하며, 리덕스 스토어에서 요청 상태와 캐시된 데이터를 가져온다.

useQuerySubscription

refetch 함수를 반환하고 모든 hook 옵션을 받는다. 엔드포인트에서 자동으로 데이터를 패치하고 컴포넌트에 캐시된 데이터를 구독한다.

useQueryState

쿼리 상태를 반환하고 skip과 selectFromResult를 받는다. 리덕스 스토어에서는 요청 상태와 캐시된 데이터를 읽는다.

useLazyQuery

fetch 함수, 쿼리 결과, 마지막 promise 정보가 포함된 튜플을 반환한다. useQuery와 비슷하지만 언제 데이터 패칭을 하는지 수동으로 제어한다.

useLazyQuerySubscription

fetch 함수와 마지막 promise 정보가 있는 튜플을 반환한다. useQuerySubscription과 비슷하지만 언제 데이터 패칭을 하는지 수동으로 제어한다.
예시에서는 useGetPostQuery같은 표준 useQuery 기반 hooks를 사용한다. 그러나 다른 hooks들도 특정한 사례에 사용할 수 있다.

참고 : https://junsangyu.gitbook.io/rtk-query/rtk-query/queries

profile
네트워크 엔지니어에서 풀스택 개발자로

0개의 댓글