ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [ Project ] RTK-Query에 Axios 입히기
    Project 2023. 9. 4. 21:29

    - RTK-Query에 Axios 를 ?

    RTK-Query란 Redux Toolkit 내의 포함되어 있고 데이터 패칭 및 서버 상태 관리를 도와주는 기능을 제공합니다.

    기본적으로 fetch를사용하여 HTTP 통신을 합니다.

    현재 진행 중인 프로젝트에서 RTK-Query를 사용 중인데, API 요청에 일괄 처리가 필요한 두 가지의 이유가 있습니다.

    1. 모든 요청 헤더에 토큰이 필요. 

    2. accessToken토큰이 만료되었을 경우, 토큰 재발급하고 갱신된 토큰을 헤더에 설정하고 재요청.

     

    1번 문제 같은 경우, RTK-Query의 prepareHeaders 요청 헤더를 수정할 수 있습니다.

    하지만 API slice마다 헤더에 토큰을 넣어주는 중복되는 코드도 발생할뿐더러

    2번 문제같은 경우는 바로 해결할 수 있는 기능이 Fetch API에는 존재하지 않습니다.

    그리하여, 위 두 가지 문제의 해결책인 Axios Interceptor를 활용하기 위해 RTK-Query에 Axios BaseQuery를 적용했습니다.

     

    - RTK-Query에 Axios 적용하기

    RTK-Query 공식 문서

    공식문서 우측 상단 Search에 'Axios baseQuery'를 검색해 주세요.

    import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
    import type { Pokemon } from './types'
    
    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 const { useGetPokemonByNameQuery } = pokemonApi

     

    공식 문서에 있는 RTK-Query의 기본 템플릿 코드입니다.

    baseQuery: fetchBaseQuery({ baseUrl: 'https://pokeapi.co/api/v2/' })

    baseQuery는 RTK Query에서 실제 네트워크 요청을 수행하는 함수를 정의하는 데 사용되는 곳입니다.

    기본적으로 RTK Query는 fetch를 사용하여 API 호출을 수행하기에 fetchBaseQuery를 사용하는 것을 확인할 수 있습니다.

    즉, fetchBaseQuery자리에 Axios로 통신하도록 코드를 구현하여 적용하면 됩니다.

     

    Customizing axiosBaseQuery 공식문서에서 Examples - baseQuery / Axios baseQuery 부분을 참고.

    공식문서를 참고하면 어렵지 않게 만들 수 있습니다.

    axios instance를 만들어줬기 때문에 baseUrl 생략하고 import한 instance 사용했습니다.

    import type { BaseQueryFn } from '@reduxjs/toolkit/query';
    import type { AxiosRequestConfig, AxiosError } from 'axios';
    import instance from './instance';
    
    const axiosBaseQuery = (): BaseQueryFn<
        {
          url: string;
          method: AxiosRequestConfig['method'];
          data?: AxiosRequestConfig['data'];
          params?: AxiosRequestConfig['params'];
        },
        unknown,
        unknown
      > =>
      async ({ url, method, data, params }) => {
        try {
          const result = await instance({ url, method, data, params });
          return { data: result.data };
        } catch (axiosError) {
          let err = axiosError as AxiosError;
          return {
            error: {
              status: err.response?.status,
              data: err.response?.data || err.message,
            },
          };
        }
      };
    
    export default axiosBaseQuery;

     

    axiosBaseQuery를 API splice에 적용

    import { createApi } from "@reduxjs/toolkit/query/react";
    import axiosBaseQuery from "./axiosBaseQuery";
    
    const END_POINT = "api/member";
    export const memberApi = createApi({
      baseQuery: axiosBaseQuery(),
      reducerPath: "memberApi",
      tagTypes: ["Member"],
      endpoints: (builder) => ({
        // 모든 멤버 정보 가져오기
        getAllMembers: builder.query({
          query: () =>({
            url:`${END_POINT}/get/v1/all-members`,
            method:"GET"
          }),
          providesTags: [{type: "Member"}]
        }),

     

    - 개선점

    Axios를 적용함으로써 이점은 명확했습니다.

    1. 기존에 각 api slice마다 prepareHeaders에 토큰을 넣어주는 코드를 interceptors.request를 통해 집약적으로 관리할 수 있습니다.

    좌측은 fetchBaseQuery를 사용할 때의 코드입니다. 우측에서는 prepareHeaders에 해당하는 코드가 interceptors.request에서 관리하여 반복되는 코드를 줄일 수 있습니다.

    2. Axios Interceptor를 활용하여 토큰 만료 시 요청을 가로채어, 에러 핸들링을 용이하게 할 수 있습니다.

     

     

    Axios 적용 완료했으니, 이어서 Axios Interceptor 활용 글을 작성하겠습니다 !

     

     

     

     

     

     

Designed by Tistory.