본문 바로가기
프로그래밍/react

[220506] 미들웨어) redux-saga

by 한코코 2022. 5. 11.

redux-saga란?

redux-saga는 redux-thunk 다음으로 가장 많이 사용되는 라이브러리다.

redux-thunk는 함수를 디스패치 할 수 있게 해주는 미들웨어였다.

redux-saga는 액션을 모니터링하고 있다가, 특정 액션이 발생하면 이에 따라 특정 작업을 하는 방식으로 사용한다.

 

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

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

이 외에도 다양한 까다로운 비동기 작업들을 redux-saga를 사용하여 처리 할 수 있다.

 

참고블로그 : https://react.vlpt.us/redux-middleware/10-redux-saga.html

 

 

 


작업을 실행하기위한 사전세팅

import { takeLatest, call, put, all, fork } from 'redux-saga/effects'
import axios from 'axios'

 

 

saga 설치하기

$ npm install redux-saga

 

 

saga 세팅하기

const reduxSaga = require('redux-saga')

 

 

saga 사용하기 - 기본형

const { createStore, compose, applyMiddleware } = require("redux");
const rootReducer = require('./reducers/index')
const reduxSaga = require('redux-saga')

const middleware = []
const enhancer = process.env.NODE_ENV !== 'production'
? compose(applyMiddleware(...middleware))
: composeWithDevtool(applyMiddleware(...middleware))

const store = createStore(rootReducer, enhancer);

 

 

 


saga의 흐름을 알기위한 구조도

 

 

 

function*으로 작성된 watchCounterUp함수.

action 값을 추적하는 것이 목적인 미들웨어에게 action값을 보내는 함수다.

dispatch( {type:'UP'} )일 경우, UP을 추적한다.

saga effect에서는 function에 *을 붙인다.

 

redux-saga/effecs에 속해있는 take메서드는 인자값을 두개 사용한다.

첫번째는 action.type : action의 type을 추적하기 위해 사용한다.

두번째는 type을 추적이 되었다면 실행할 function*으로 작성된 함수명을 작성해야한다.

 

takeLatest는 동일한 명령이 여러번 발생했을때 가장 마지막에 명령을 실행한다.

takeEvery는 동일한 명령이 여러번 발생했을때 모든 명령을 실행한다.

export default function* watchCounterUp(){
    yield takeLatest('COUNTER/UP_REQUEST',counterUp) // 이벤트가 발생했을때!
    yield takeLatest('COUNTER/DOWN_REQUEST',counterDown)
}

 

 

 

 

function*으로 작성된 counterUp함수

미들웨어에서 백과 통신하는 API에게 요청을 하고 응답을 받는 함수다.

yield를 만나면 코드 실행이 잠시 멈추는 기능을 이용했으며, yield가 없으면 promise처리가 되어서 pending 상태로 떨어진다.

 

redux-saga/effecs에 속해있는 call에는 인자값이 두개 들어간다. (동기처리 함수)

첫번째는 사용할 함수명

두번째는 첫번째 인자에 들어간 함수에 대한 인자값이 들어간다.

 

put은 dispatch와 같은 역할을 한다.

put에 들어온 type으로 action을 실행한다.

function* counterUp(action){
    // 여기함수에서 API 내용 작성
    try {
        console.log('SAGA')
        const result = yield call(upAPI,action.payload)
        
        yield put({
            type:'COUNTER/UP_SUCCESS'
            // dispatch 성공에대한 프로세스
        })
    } catch (e) {
        yield put({
            type:'COUNTER/UP_FAILURE'
            // dispatch 실패에대한 프로세스 
        })
    }
}

 

 

 

 

payload값을 받는 upAPI 함수

백과 통신하는 API함수다.

action값을 받았을때 type이 counterUp에서 처리되었다면, payload값은 upAPI에서 처리된다.

비동기적으로 이루어지며 1초 뒤에 무조건 성공이란 결과를 내놓는 코드.

 

api에 관한 블로그

https://meetup.toast.com/posts/92

https://react.vlpt.us/integrate-api/01-basic.html

async function upAPI(payload){
    console.log(payload)
    return new Promise( (res,rej)=>{
        setTimeout( ()=>{
            res(true)
        },1000 )
    } )
}

 

 

 

 

내보낸 watchCounterUp을 실행하기 위한 index.js

함수들이 여러개일때 배열에 담아서 필요한 만큼 쪼개서 사용할 수 있는 all

여기까지 와야 비로서 action의 type인 COUNTER/UP의 추적이 끝난다.

import { all } from 'redux-saga/effects'
import takersAll from './takersAll'
import watchCounterUp from './counterSaga' // 가져와서 사용
import userSaga from './userSaga'

console.log( userSaga )

export default function* rootSaga(){
    yield all([ watchCounterUp() ])
}

 

 

 


결과

아래와 결과가 나와서 현재 어떤 상태인지 알 수 있다(추적한 결과).

클릭 이벤트로 발생한 COUNTER/UP_REQUEST

중간 middleware에서 발생한 COUNTER/UP_SUCCESS

 

middleware를 사용한다 = saga를 통해서 내용을 수정하겠다.

댓글