ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [REACT] Redux, Redux-Thunk, Redux-Saga
    React, Next 2022. 8. 14. 01:33

    Redux 세팅 방법

    store > configureStore.js

    import { createWrapper } from "next-redux-wrapper"
    import { applyMiddleware, compose, createStore } from "redux"
    import { composeWithDevTools } from "redux-devtools-extension"
    import reducer from "../reducers"
    
    const configureStore = () => {
        const middlewares = []
        const enhancer =
            process.env.NODE_ENV === "production"
                ? compose(applyMiddleware(...middlewares))
                : composeWithDevTools(applyMiddleware(...middlewares)) // 개발자모드에서 DevTools 사용 세팅한다.
        const store = createStore(reducer, enhancer)
        return store
    }
    const wrapper = createWrapper(configureStore, {
        debug: process.env.NODE_ENV === "development",
    })
    
    export default wrapper

    middlewares

    리덕스에 없는 기능을 추가해서 성능을 확장시켜주는 역할을 한다. 리덕스 세팅에 middlewares 안에 Thunk나 Saga를 추가적용 할 수 있다.

     


    Redux-Thunk / Redux-Saga

    둘 다 비동기 action을 dispatch할 수 있도록 도와주는 역할을 한다.

    아래 코드를 보면 setTimeout 함수 안에 dispatch를 한 것을 볼 수 있다.

    const INCREMENT_COUNTER = 'INCREMENT_COUNTER'
    
    function increment() {
      return {
        type: INCREMENT_COUNTER
      }
    }
    
    function incrementAsync() {
      return dispatch => {
        setTimeout(() => {
          // Yay! Can invoke sync or async actions with `dispatch`
          dispatch(increment())
        }, 1000)
      }
    }

    비동기 action을 dispatch 하게되면 장점은 무엇일까?

    하나의 비동기 액션 안에 여러개의 동기 액션을 할 수 있다

    예를 들면 axios 요청을 보낼 때 LoadPostRequest 액션을 dispatch하고, 성공했을 땐 LoadPostSuccess를, 실패했을 땐 LoadPostFailer dispatch하는 식으로 여러번의 액션을 보낼 수가 있다.

     


    Redux-Thunk 사용방법

    우선 패키지를 설치한다.

    npm i redux-thunk

    import 해준 모듈을 middlewares 배열에 넣어주면 된다.

    ...
    import thunkMiddleware from 'redux-thunk';
    ...
    
    const configureStore = () => {
        const middlewares = [thunkMiddleware]
        ...
    }
    ...
    
    export default wrapper

     

    Redux-Thunk가 제공하는 기능 외에 내맘대로 로직을 커스텀 하고싶다면?

    https://github.com/reduxjs/redux-thunk/blob/master/src/index.ts

     

    GitHub - reduxjs/redux-thunk: Thunk middleware for Redux

    Thunk middleware for Redux. Contribute to reduxjs/redux-thunk development by creating an account on GitHub.

    github.com

    Redux-Thunk 깃허브에서 코드를 타고 들어간뒤

    위 코드가 Redux-Thunk의 핵심이다. 아래 코드를 통해 자세히 살펴보자.

    ({ dispatch, getState }) => next => action => {
        // action이 원래는 객체인데 redux-thunk에서는 action을 function으로 둘 수 있다. action이 function이면 지연함수이기 떄문에 그 액션을 나중에 실행시켜줄 수 있다.
        // 이 action이 실제로 함수라면 호출하고 결과를 반환한다.
        if (typeof action === 'function') { 
        	return action(dispatch, getState)
        }
    
        // 그렇지 않으면 평소와 같이 미들웨어 체인 아래로 작업을 전달한다.
        return next(action)
    }

     

    하지만 위 코드를 수정하면서 내 마음대로 dispatch가 일어나기 전에 로직을 추가/수정 할 수 있다.

    const loggerMiddleware = ({ dispatch, getState }) => next => action => {
        console.log(action)
        return next(action)
    }
    
    const configureStore = () => {
        const middlewares = [thunkMiddleware, loggerMiddleware]
        ...
    }

    고차함수로 이루어져 있는 저 loggerMiddleware 라는 함수에서 next, action과 같은 매개변수를 가져오기 때문에, 이것을 활용해 dispatch가 이루어지기 전에 먼저 실행할 로직을 넣어줄 수 있다. 위 코드의 경우 dispatch가 이루어지기 전에 action을 콘솔로 찍어준다.

    실제로 로그인, 로그아웃 action을 요청한 뒤 개발자도구를 열어보니 콘솔에 찍힌 것을 확인할 수 있다.

     


    Redux-Saga

    Redux-Thunk보다 더 많은 기능을 제공해준다. 예를들어 클릭을 짧은시간에 여러번 클릭했을 땐 어떻게 처리할 것인지? 이런 부분을 Thunk에서는 직접 구현해야 하지만 Saga에서는 takeLatest, trottle 등 한번에 해결해주는 여러가지 메소드가 존재한다.

    Redux-Saga 사용방법

    npm i redux-saga

    리덕스 사가의 경우에는 여기저기 세팅할 부분들이 좀 있다.

    1. 우선 import를 해준 뒤 sagaMiddleware라는 변수에 createSagaMiddleware를 호출하여 넣어준다.

    2. middlewares 배열에 sagaMiddleware를 넣어준다.

    3. store 변수에는 sagaTask라는 메서드가 있는데, 아래 코드에 '핵심' 이라고 쓰여있는 부분의 세팅을 하자.

    import createSagaMiddleware from "redux-saga"
    import rootSaga from "../sagas"
    
    const configureStore = () => {
        const sagaMiddleware = createSagaMiddleware()
        const middlewares = [sagaMiddleware, loggerMiddleware]
    	...
        const store = createStore(reducer, enhancer)
        store.sagaTask = sagaMiddleware.run(rootSaga) 🔥핵심
        return store
    }
    
    ...

     

    Generate 함수

    설명 넣기


    Saga의 다양한 Effect

    • all : fork나 call로 실행하는 것들을 동시에 전부 실행할 수 있게 해준다.
    • take : 지정한 action이 실행될 때까지 기다리겠다. 지정된 action이 실행되면 지정해둔 generate 함수를 호출한다.
    • fork : 함수를 실행하는 것. 비동기 함수 호출. API가 반환되는 것을 받아오기 전에 다음 코드가 실행되어버린다.
    • call : 함수를 실행하는 것. 동기함수 호출. API가 반환해준 것을 받아올 수 있다. async await 같은 느낌이라고 보면 된다.
    • put : dispatch라고 보면 된다. 액션을 실행시키는 놈인데, Rest API를 통해 반환받은 값을 함께 전달하며 실행시킬 수 있다.
    • takeEvery : take로 만든 함수는 한번 실행되면 사라져버리는데, 이건 그 함수를 무한하게 사용할 수 있다. 마치 while(true)로 감싸는 느낌이다.
    • takeLatest🔥 : 클릭을 실수로 2번 눌렀을 때 앞에 누른건 무시되고 마지막 클릭만 실행시킨다. 주로 이거 쓴다.
    • takeLeading : takeLatest과 비슷하지만 이건 맨 첫번째 클릭만 실행되고 나머지를 무시한다.
    • throttle🔥 : 시간을 설정해두고 그 시간동안에는 클릭을 여러개 해도 하나만 보내지도록 한다. 이것도 중요
    • debounce : 검색창에 타이핑할 때 자동완성 데이터를 불러오는 부분에서 주로 사용한다. 어떤 단어가 완성될 때 요청보내는 식으로 정할 수 있다. throttle과 기능적으로 비슷한데 미묘한 차이가 있다고 하니 사용할 때 찾아보도록 하자!
    • delay : 정해준 시간이 지난 뒤에 다음 코드를 실행시키게 한다.

    이외에도 takeMaybe 등이 있다.

     

     

     

     

     

    'React, Next' 카테고리의 다른 글

    체크박스, 라디오버튼 만들기  (0) 2022.08.22
    텍스트에디터?  (0) 2022.08.18
    버츄얼 돔?  (0) 2022.08.15
    불변성에 대하여  (0) 2022.08.14
    react.lazy와 suspense  (0) 2022.08.14
Designed by Tistory.