Redux 에서 비동기 처리하기 (소개)

Yeojin Choi·2022년 5월 10일
0

User 의 정보가 redux store 에서 state 로 관리되고 있을 때, 수정 사항이 발생한 경우 DB 의 정보를 수정함은 물론 redux store 의 state 도 변경되어야 한다.

useEffect 내부에서 axios 를 통해 서버에 정보를 전달하고, state 를 업데이트 해야한다면

  1. Component 의 useEffect 내부에서 axios 를 사용해 요청
  2. 백엔드 서버에서 DB Update 및 응답
  3. 응답받은 데이터를 store 의 state 에 업데이트
  4. 해당 state 를 구독하고 있는 컴포넌트 리렌더링

의 순서로 일어날 것이다.

위와 같은 방법도 있지만, Redux 의 미들웨어를 사용하여 비동기 작업을 관리할 수 있다.

미들 웨어

리액트 웹 애플리케이션에서 API 통신으로 서버에 데이터 요청 시 로딩 중인지 로딩 완료인지, 요청에 성공했는지 실패했는지 및 요청이 성공하면 응답에 대한 상태 관리가 필요하다.
Redux 는 이러한 비동기 작업을 관리하기 위해 redux-saga, redux-thunk 등의 라이브러리를 통한 미들웨어 를 지원한다.

Action dispatch -> 비동기 로직 실행 -> 리듀서를 통해 액션 발생 -> store update 가 일어나며 비동기 로직이 component 에서 store 로 이동하게 된다.

redux-thunk

  • thunk : 특정 작업을 나중에 하도록 미루기 위해 함수 형태로 감싼 것
  • thunk 함수를 만들어서 dispatch하면 미들웨어가 thunk 함수를 전달 받아 스토어의 dispatchgetState 를 파라미터로 넣어 호출 → action 객체 반환
  • 액션의 dispatch 를 delay 하거나 특정 조건에서 dispatch 되도록 한다.
  • 시작, 성공, 실패, 완료 4가지 형태 처리를 위해 각각 코드를 구간별로 디스패치 해야한다.
  • API 중복을 방지하기 위해 취소하고 새로 받은 데이터로 실행하는 등 추가액션을 위한 코드가 많아진다.
  • 사용 환경 : API 요청, 다른 액션 디스패치, 현재 상태 조회
  • 장점 : 간단하다
  • 단점 : 테스트의 복잡성, 중지 불가 등 기능의 제한

redux-saga

  • Generator 문법을 기반으로 worker 와 watcher 로 구성된다.
  • 특정 액션을 모니터링하도록 하고, 해당 액션이 주어지면 이에 따라 제너레이터 함수(사가)를 실행하여 비동기 작업을 처리 후 액션을 디스패치한다.
  • takeLatest 함수를 사용해 가장 최근 것만 실행하고 이전 작업을 자동 취소할 수 있다.
  • yield 키워드를 사용해 함수 실행을 중간에 멈추고 원할때 재개할 수 있다.
  • 사용 환경 : 요청 취소 처리, API 요청 실패 시 재요청, 웹소켓 사용 시 효율적으로 코드 관리, 특정 액션 발생 시 다른 액션이 디스패치 되게 하거나 자바스크립트 코드 실행
  • 장점 : 쉬운 테스트
  • 단점 : 학습 장벽 존재

장점

비동기 처리 로직 이 action creator 함수에서 처리된다. 이를 통해 UI 영역과 관심사를 분리 할 수 있고 component 의 재사용성을 높일 수 있다는 장점이 있다.

데이터를 fetching 한 후 store에 저장하여 필요한 곳에서 사용하여 Redux Store 를 Backend 상태에 대한 Data Cache로 사용할 수 있게 된다.

단점

하지만 Backend 데이터와 Frontend 데이터를 최신으로 유지하기 위해 주기적으로 refetching 하여 두 곳에 존재하는 데이터 상태를 동기화해주어야 하는 작업이 필요하다. 이에 따라 Redux store 에서 fetching 과 관련된 상태를 관리하고 주기적인 refetching 로직이 추가되어야 하기 때문에 store 가 비대해지고 store 내 state 에 대한 관심사 분리가 어렵게 된다.

이러한 문제를 Data Fetching Library 를 통해 해결할 수 있다.

Data Fetching Library

장점

  1. 동일한 API 요청이 발생할 경우 1번만 실행
  2. 데이터가 dirty 해진 경우 적절한 시점에 알아서 업데이트
  3. Global state / Server State 관심사 분리
  4. 어떤 데이터를 언제 Fetch 하면 되는지 목표만 기술하여 선언적 프로그래밍을 가능하게 해줌

특징

  • 동일한 API 요청이 발생할 경우 1번만 실행
  • 데이터가 dirty 해진 경우 적절한 시점에 알아서 업데이트
  • Global state / Server State 관심사 분리
  • 어떤 데이터를 언제 Fetch 하면 되는지 목표만 기술하여 선언적 프로그래밍을 가능하게 해줌

React Query

Server State 를 관리하는 라이브러리. 데이터 Fetching, 백그라운드에서 데이터 업데이트, Optimistic Updates, 캐싱과 Key를 통한 전역 상태와 같은 사용 등 기능 제공

  • API 통신을 위한 여러 함수를 useQuery hook 을 통해 제공

    // 첫번째 인자 : Unique Key, 해당 key 와 비동기 작업 맵핑 필요
      const { isLoading, error, data, isFetching } = useQuery("repoData", () =>
        fetch(
          "https://api.github.com/repos/tannerlinsley/react-query"
        ).then((res) => res.json())
      );
    		```
    
  • QueryClient : React Query가 Client에서 관리하는 Server State들을 Key를 통해 꺼내서 사용 가능

    const queryClient = new QueryClient();
    
    export default function App() {
      return (
        <QueryClientProvider client={queryClient}>
          <Example />
        </QueryClientProvider>
      );
    }
  • useMutation : 서버의 데이터 변경 요청을 할 때 사용하는 hook. Create, Update, Delete 요청과 같이 API 통신으로 Server State에 Side Effect가 일어나는 경우에 사용

profile
프론트가 좋아요

0개의 댓글