yeahzy
주말에 몰아쓰는 개발일기
yeahzy
전체 방문자
오늘
어제
  • 분류 전체보기 (22)
    • 주말에 쓰는 개발일기 (20)
      • javascript (10)
      • java (1)
      • react-native (5)
      • react (2)
    • 모든 일은 평일에 이루어지지 (2)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • opener 안될 때
  • event.stopPropagation()
  • showModalDialog
  • fileupload
  • next.js기초
  • 개발자역량강화로드맵
  • event.preventDefault()
  • showModalDialog.js
  • 신입개발자로드맵
  • 크롬 opener
  • 크롬개발자도구오류
  • popup에서 부모창 함수 호출
  • window.opener
  • popup opener
  • 파일업로드
  • javascript
  • Java
  • javascript opener오류
  • Ajax
  • 프론트엔드로드맵

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
yeahzy

주말에 몰아쓰는 개발일기

주말에 쓰는 개발일기/react

[React Query] 적용기

2022. 8. 17. 23:58

요즘 이직을 위해 react 를 독학하며 여러 프로그램들을 만들어보고 있다.

역시 직접 만들다보니 더 깊게 알아가게 되고 다른 라이브러리들도 많이 사용해볼 수 있게 되었다.

최근 원티드 프리온보딩 프론트엔드 과정을 통해 React Query 라는 라이브러리를 학습하게 되었다.

개념을 숙지하는 것에 많이 헷갈려서 포스팅을 통해 개념을 정리해보고자 한다.

 

Vuex 

공식문서 : https://v3.vuex.vuejs.org/kr/

3년 전 학원을 수료하면서 프론트엔드에 사용했던 기술은 vue.js 였다.

전역관리를 위해 Vue.js 애플리케이션에 대한 상태관리 패턴의 라이브러리인 Vuex 를 사용했는데, 당시에도 javascript jsp를 열심히 배우다가 SPA 프레임워크의 개념을 익히려니 헷갈리고 많이 어려웠던 것 같다.

Vuex에서는 Action에서 비동기처리를 같이 하여 서버에서 받은 데이터를 store에서 처리하였었다. (링크)

 

Redux

공식문서 : https://ko.redux.js.org/

Redux의 기본 개념인 reducer 는 순수함수이다. 동일한 파라미터를 주었을 때 항상 같은 값을 리턴하고, 외부상태를 변경하지 않는 함수를 순수함수라고 한다.

이러한 개념 때문에 비동기처리는 React-saga, React-thunk 등의 미들웨어를 필수로 사용해야 한다.

 

Redux를 적용하던 중..!

비동기처리를 위한 미들웨어를 학습하기 전이라 view 단에서 api를 모두 넣어 구현하고 있었고, api를 분리하는 것을 필요로 하고 있었다. SWR이나 react query를 학습해보기를 권해주신 분이 계셔서 공부하려던 찰나, 원티드 프리온보딩에 참여하게 되어 좋은 기회에 react query 를 학습해볼 수 있었다.

 

React Query

처음에 React Query 를 접하고 다른 사람들의 소스도 보고 적용해보려고 하였으나 쉽지가 않았다.그 이유는 내가 Redux 에서 api를 관리하는 미들웨어 중에 하나라는 착각을 가지고 바라보았기 때문이다. 개념을 조금 더 깊게 알아보았더라면 이러한 오류는 발생하지 않았을 것이다.

 

Redux + middleware vs react query

redux는 순수함수, 단일 store 를 가지고 있으며, action을 일으켜서 middleware 를 통해 가지고 온 서버 데이터를 redux에 저장하여 사용한다. 또한, 이 데이터의 영속성을 위해 react-persist 를 사용하기도 한다.

하지만 이미 그 데이터는 서버에 저장되어있는 (데이터 베이스에 이미 담겨있는) 데이터이다. 단일 store (진실한 정보의 원천) 이라는 개념과도 맞지 않다. 또한, 혹시 서버에서 변경된 데이터가 다시 클라이언트 store에 저장하기 위해서는 Action 이 일어나 store 의 상태 값을 바꿔주어야 최신화 된 데이터를 볼 수 있을 것이다.

서버에서 주기적으로 데이터를 가지고 온다면, 클라이언트에 굳이 데이터를 담아 사용할 필요도 없고 최신 데이터를 유지할 수 있을 것이다. React Query 에서는 이러한 단점을 보완하기 위해 클라이언트의 상태와 서버의 상태를 따로 관리하도록 해준다.

 

특징

1. 캐싱 : 자주 사용하는 데이터를 저장해둠.

2. 동일한 데이터에 대한 중복된 요청을 제거

3. 데이터가 오래되었는지를 파악하고 최신 데이터로 업데이트

4. 데이터가 update 될 경우 자동으로 데이터를 가져오는 api를 실행

5. 보일러 플레이트 코드가 줄어듬

6. 종속성이 없어 쉽게 적용이 가능

 

이상의 특징은 사용해보면서 하나하나 익혀가보아야겠다.

 

사용법

$ npm i @tanstack/react-query
# or
$ yarn add @tanstack/react-query

공식문서에 있는 간단한 예제를 첨부한다.

//_app.tsx (전역 셋팅)
import {
  useQuery, //데이터를 가져오기 위한 api
  useMutation, //데이터를 바꾸기 위한 api
  useQueryClient,
  QueryClient,
  QueryClientProvider,
} from '@tanstack/react-query'
import { getTodos, postTodo } from '../my-api'

// Create a client //클라이언트 생성
const queryClient = new QueryClient()

function App() {
  return (
    // Provide the client to your App //provider 셋팅
    <QueryClientProvider client={queryClient}>
      <Todos />
    </QueryClientProvider>
  )
}

//todos.tsx (쿼리를 사용하는 곳)
function Todos() {
  // Access the client //클라이언트 접근
  const queryClient = useQueryClient()

  // Queries (['todos']는 query key 이다. getTodos가 api 함수이다.)
  // useQuery(queryKey, queryFn, options)
  const query = useQuery(['todos'], getTodos)

  // Mutations (postTodo가 api함수이다.)
  // useMutation(mutationKey, mutationFn, options)
  const mutation = useMutation(postTodo, {
    onSuccess: () => {
      // Invalidate and refetch //이전 데이터는 무효화, 데이터 다시 get
      queryClient.invalidateQueries(['todos'])
    },
  })

  return (
    <div>
      <ul>
        {query.data?.map(todo => (
          <li key={todo.id}>{todo.title}</li>
        ))}
      </ul>

      <button
        onClick={() => {
          mutation.mutate({
            id: Date.now(),
            title: 'Do Laundry',
          })
        }}
      >
        Add Todo
      </button>
    </div>
  )
}

render(<App />, document.getElementById('root'))

getTodos는 이러한 형태의 API 일 것이다.

const clientApi = axios.create({
  baseURL: "http://localhost:8080",
});

const getTodos = async (): Promise<{ data: ITodo[] }> => {
    const { data } = await clientApi.get(`/todos`, {
    headers: {
        Authorization: getToken(),
    },
});
    return data;
};

 

도대체 api로 가져오는 소스랑 redux는 어떻게 연결되는거야!? 에서 막혔었다. (우선 적용해보자는 무모한 용기의 잘못된 사용.) api로 가져오는 데이터와 client의 순수한 데이터를 분리하려고 react query를 쓰는 거라고 과거의 나의 귓속에 속삭여본다. 

 

redux는 이제 완전히 client의 데이터만을 제공하게 되었다. 예를 들면, 다크모드와 같은 UI에 대한 상태가 client만을 위한 상태 데이터일 것이다.

 

 

참조 

Tanstack Query 공식문서

 

카카오페이 프론트엔드 개발자들이 React Query를 선택한 이유

원티드 프리온보딩 프론트엔드 과정 강의

기억보다 기록을 노경환님 블로그

'주말에 쓰는 개발일기 > react' 카테고리의 다른 글

[React Query] 적용기2  (0) 2022.08.27
    '주말에 쓰는 개발일기/react' 카테고리의 다른 글
    • [React Query] 적용기2
    yeahzy
    yeahzy
    주말에 몰아 쓰려고 만들었는데 생각보다 주말은 빠르다..

    티스토리툴바