FrontEnd/React.js

[React.js] redux-thunk vs redux-saga

푸고배 2022. 3. 28. 20:38

redux-thunk와 redux-saga는 리덕스에서 비동기 작업을 돕는 미들웨어이다.

redux-thunk

리덕스에서 비동기 작업을 처리할 때 가장 많이 사용하는 미들웨어로 이 미들웨어를 사용하면 액션 객체가 아닌 함수를 디스패치할 수 있다. 함수를 디스패치할 때는, 해당 함수에서 dispatch와 getState를 파라미터로 받아와야하고, 이 함수를 만들어주는 함수를 thunk라고 부른다. 따라서 리덕스 스토어의 상태에 접근하거나 또 다른 액션을 디스패치하는 것이 가능하다. 

 

thunk 미들웨어의 문제점은 action에서 너무 많은 일을 한다는 점이다. 액션 생성자는 type과 payload가 담긴 객체를 생성해서 반환하는 역할을 수행하기로 했는데, thunk 미들웨어에서는 API 요청이나 비동기 처리를 함으로써 본래의 역할이 모호해진다. 어떤 경우는 객체를 반환하고, 또 어떤 경우는 함수를 반환한다.

redux-saga

thunk가 함수를 디스패치할 수 있게 해주는 미들웨어였다면, saga는 액션을 모니터링하고 있다가 특정 액션이 발생했을 때, 미리 정해둔 로직에 따라 특정 작업이 이루어지는 액션에 대한 리스너이다.

여기서 특정 작업이란, 특정 자바스크립트를 실행하는 것일 수도 있고, 다른 액션을 디스패치 하는 것일 수도 있고, 현재 상태를 불러오는 것일 수도 있다. 

redux-saga는 redux-thunk로 못하는 다양한 작업들을 처리할 수 있다. 예를 들면

  1. 비동기 작업을 할 때 기존 요청을 취소할 수 있다.
  2. 특정 액션이 발생했을 때 이에 따라 다른 액션이 디스패치 되도록 하거나, 자바스크립트 코드를 실행할 수 있다.
  3. 웹 소켓을 사용하는 경우 Channel이라는 기능을 사용해 더욱 효율적으로 코드를 관리할 수 있다.
  4. API 요청이 실패했을 때 재요청하는 작업이 가능하다.

redux-saga는 다양한 상황에 쓸 수 있는 만큼, 제공되는 기능도 많고 러닝커브가 있다. 자바스크립트 초심자라면 생소할만한 Generator 문법을 사용하며, 이 문법을 이해하지 못하면 redux-saga가 어렵게 다가올 수 있다.

 

redux-saga effects

redux-saga에는 saga의 활용을 돕기 위한 다양한 effects들이 존재한다. 이 effects들은 미들웨어에서 활용할 수 있는 정보들을 담고 있는 자바스크립트 객체의 일종이다. 이 effects들을 활용하여 saga를 보다 효과적으로 사용할 수 있다. 아래는 많이 쓰이는 대표적인 effects 들이다.

all

all effect는 제너레이터 함수들이 들어있는 배열을 인자로 받는다. 이렇게 들어온 제너레이터 함수들은 all effect 안에서 병렬적으로 기능을 수행하며, 이 함수들이 모두 resolve될 때까지 기다린다. Promise.all과 비슷한 기능이라고 생각하면 된다.

call

call effect는 함수를 실행시키는 effect이다. 이 effect의 첫 번째 인자에는 함수를 넣고, optional로 나머지 인자에 해당 함수에 넣을 인자를 넣을 수 있다. 일반 javascript의 바인딩 함수 call과 유사하다.

fork

fork effect 역시 함수를 실행시키는 effect로 call과 fork의 차이점은 fork는 함수를 비동기 실행하며, call은 함수를 동기 실행한다. 따라서 순차적으로 함수가 실행되어야 하는 api 요청 함수 등의 경우에는 call을 사용하며, 그 외의 비동기 로직에는 fork를 사용한다.

put

put effect는 특정 액션을 dispatch하는 effect이다. 위의 예시에서 보면 제너레이터 함수 내부에서 특정 액션을 dispatch하고 있음을 확인할 수 있다.

takeEvery/ takeLatest

takeEvery와 takeLatest는 인자로 들어온 액션에 대해 특정 로직을 실행시켜주는 effect이다. takeEvery와 takeLatest의 차이는 takeEvery의 경우, 인자로 들어오는 모든 액션에 대해 로직을 실행시켜주는 반면, takeLastest는 기존에 실행 중이던 작업이 있을 경우 이를 취소하고, 가장 마지막으로 실행된 작업만 실행한다는 점이다.

 

어떤 상황에서 사용해야할까?

thunk는 saga에 비해 보일러플레이트 코드가 적고 이해하기 쉽다는 장점이 있으며, 그만큼 서비스에 빠르게 적용이 가능하다. 따라서 서비스의 규모가 작은 경우 thunk를 선택할 수 있다. 하지만, thunk의 경우 초보자가 잘못 사용할 경우 복잡한 async 로직으로 인해 콜백 hell을 발생시킬 수 있으며, unit test가 어려운 구조로 되어있다는 단점이 있다.

 

saga는 thunk에 비해 초기에 구현해야하는 보일러플레이트의 양이 많고, 자바스크립트 ES6의 제너레이터 개념을 이해하고 있어야하므로 초기 러닝커브가 높은 편이다. 하지만, thunk에 비해 규모가 큰 프로젝트에 적용하기 용이하고, saga의 여러 effects를 활용하면 더 깔끔한 로직 구현이 가능하다. 

 


Reference

 

10. redux-saga · GitBook

10. redux-saga 소개 redux-saga는 redux-thunk 다음으로 가장 많이 사용되는 라이브러리입니다. redux-thunk의 경우엔 함수를 디스패치 할 수 있게 해주는 미들웨어였지요? redux-saga의 경우엔, 액션을 모니터

react.vlpt.us

 

Redux Thunk & Saga

프론트엔드 개발을 React로 하다보면 다양한 이유로 Redux를 만나게 되고 활용하게 됩니다. 그리고 Redux를 접해서 사용하다보면 자연스레 Redux Thunk와 Redux Saga 역시 접하게 됩니다. 이 두 리덕스 미

shinejaram.tistory.com

 

[React] Redux와 Redux 미들웨어 - thunk, saga

Ego sum operarius studens

devsoyoung.github.io

 

반응형