[Redux] Redux(3) - 미들웨어, immer로 불변객체 관리

권준혁·2020년 11월 1일
0

Redux

목록 보기
2/3
post-thumbnail

안녕하세요
미들웨어에 대한 포스팅입니다.

미들웨어를 이용하면 반복적으로 구성해야되는 로직을 쉽게 작성할 수 있습니다.

Nodejs에서 express모듈로 RestAPI서버를 만들어봤다면 쉽게 이해가 됩니다. Request가 들어오면 엔드포인트로 전달되기전에 미들웨어를 거쳤습니다.
Redux에서도 마찬가지로 Action이 Dispatch되면 Reducer로 전달되기전에 미들웨어가 실행됩니다.

이 미들웨어에서 리듀서에서 발생한 예외를 서버로 전송하는 목적으로 사용할 수도 있고, 상탯값 변경시의 로깅 등을 할 수 있습니다.

  • 기본구조

    const Middleware = store => next => action => next(action);
  • 기본구조

const Middleware = function(store) {
  return function(next) {
    return function (action) {
      return next(action)
    }
  }
}

위 코드에서처럼 중첩된 함수로 되어있어 store와 action객체를 이용한 미들웨어 처리가 가능합니다.
store의 상탯값을 호출해서 사용할 수도있고, action객체의 payload를 이용할 수도 있습니다.

미들웨어 설정하기

import { createStore, applyMiddleware } from 'redux';
const middleware1 = store => next => action => {
   console.log('middleware start1');
   const result = next(action);
   console.log('mideleware end1');
   return result;
}
const middleware2 = store => next => action => {
   console.log('middleware start2');
   const result = next(action);
   console.log('mideleware end2');
   return result;
}
const Reducer = (state, action) => {
   console.log('reducer');
   return state;
}
const store = createStore(Reducer, applyMiddleware(middleware1, middleware2));
store.dispatch({type:'someAction'});

applyMiddleware를 사용해 여러개의 미들웨어를 정의할 수 있습니다.
createStore함수의 두 번째 인자로 넣어줍니다.

결과

middleware start1
middleware start2
reducer
middleware end1
middleware end2

만약 미들웨어를 정의하는 부분에서return next(action)처럼 바로 리턴하지않고, next(action)를 result변수에 담은 후 리턴했기 때문에 미들웨어가 종료된 뒤 실행할 코드를 작성할 수 있습니다.
따라서, 각 미들웨어는 reducer호출 전 후의 코드를 작성할 수 있습니다.

첫 번째 미들웨어인 middleware1은 다음 미들웨어 함수를 실행합니다. 마지막 미들웨어인 middleware2의 next함수는 store가 원래 갖고있던 dispatch메서드를 호출합니다.


immer

immer는 불변객체를 관리하도록 도와주는 모듈입니다.
State를 불변객체로 관리하고자 할 때 Spread Syntax를 많이사용합니다.

immer : Documentation

전화번호를 수정해보겠습니다.

  • 다음은 SpreadSyntax를 이용하는 코드입니다.
    const obj = {
      name : 'junhyuk',
      info : {
        address : 'a b c d e f',
        phone : '010-0000-0000',
        family : {
           ...
        }
      }
    }
    const newObj = {
      ...obj, 
      info:{
        phone : '01000000000'
        ...obj.info,
        family: {
          ...obj.info.family
        }
      }
    }

중첩되는 구조가 조금만 깊어져도 복잡해집니다.
immer를 사용하면 쉽게 불변객체를 관리 할 수 있습니다.

  • immer를 사용한 코드
import produce from 'immer';
const obj = {
    name : 'junhyuk',
    info : {
      address : 'a b c d e f',
      phone : '010-0000-0000',
      family : {
         ...
      }
    }
}
const newObj = produce(obj, draft=>{
    draft.info.phone = '01000000000'
})

immer를 이용해 Reducer 작성하기

function reducer(state = INITIAL_STATE, action) {
   return produce (state, draft=> {
      switch (action.type) {
        case ADD:
          draft.todos.push(action.todo);
          break;
        case REMOVE_ALL;
          draft.todos = [];
          break;

          ...

        default:
         break;   
      }
   }) 
}

produce메서드가 action.type에 따라 다른 객체를 리턴합니다.
immer를 사용했기 때문에 push메서드를 사용해도 produce 메서드가 새로운 객체를 리턴합니다.


profile
웹 프론트엔드, RN앱 개발자입니다.

0개의 댓글