Redux middleware

Rosevillage·2023년 3월 1일
0

Middle ware

리덕스에서 middleware란 dispatch 기능에 동작을 추가하는 함수로 action을 받아 추가 동작을 수행한 이후에 next를 통해 다음 middleware나 reducer로 전달한다.
express의 middleware와 비슷하다고 볼 수 있다.

middleware는 액션을 보내는 순간부터 스토어에 도착하는 순간까지 사이에 서드파티 확장을 사용할 수 있는 지점을 제공하며, 로깅이나, 충돌 보고, 비동기 API와의 통신이나, 라우팅 등에 사용할 수 있다.

const middleware = store => next => action => { // 1
  // do something
}

function middleware(store) { // 2
  return function (next) {
    return function (action) {
      // do something
    };
  };
};

1번이 미들웨어의 기본적인 모습이며, 2번은 1번을 함수 선언식으로 표현한 모습이다.

매개변수

  • store: redux store의 인스턴스

  • next: action을 다음 middleware 혹은 다음 middleware가 없을 경우 reducer로 전달하는 함수

    middleware 내부에서 next 대신 dispatch를 사용하면 다른 액션을 추가적으로 발생시킬 수 있으며, middleware 목록의 시작 부분에서 처리를 다시 시작하게 된다.

  • action: 현재 처리하고 있는 action 객체

middleware를 포함한 상태 변경을 다음과 같이 동작한다.

middleware가 action이 reducer도 전달되기 전 단계에서 동작을 추가 할 수 있다는 특성을 통해 위에서 나열한 로깅 등의 기능들에 사용할 수 있다.

middleware 예시

충돌 보고와 같이 개발을 위해 에러를 재현하는 것을 예로 들었을때, action을 보내 에러가 날 때마다 스택과 에러를 일으킨 액션, 현재 상태를 Sentry에 전달해 에러를 쉽게 생성해 볼수도 있다.

const crashReporter = store => next => action => {
  try {
    return next(action);
  } catch (err) {
    console.error('Caught an exception!', err);
    Raven.captureException(err, {
      extra: {
        action,
        state: store.getState()
      }
    });
    throw err;
  }
}

위와 같이 작성 할 수 있는데, action이 생성될때마다 try..catch 문으로 에러 발생 여부를 파악해 상황에 따라 동작할 수 있다.

action과 state의 추적을 위해 로깅이 필요한 경우 다음과 같이 작성해 action이 일어날 때마다 콘솔에서 action 객체와 state를 확인 할 수도 있다.

const logger = store => next => action => {
  console.group(action.type);
  console.info('dispatching', action);
  let result = next(action);
  console.log('next state', store.getState());
  console.groupEnd(action.type);
  return result;
};

위의 코드는 action 객체와 변경된 state를 콘솔에 출력한다.

middleware 적용

작성한 middleware는 스토어에 적용해야 사용할 수 있다.

// createStore
const store = createStore(rootReducer, applyMiddleware(myLogger));
// configureStore => middleware 전달시 아무 조치 없이 전달하면 applyMiddleware로 처리한다. => 기본값으로 있는 middleware 사용 못함
const store = configureStore({rootReducer,
  middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(logger)});

configureStore의 경우 주어진 middleware 배열을 자동적으로 applyMiddleware로 전달한다.

middleware를 추가하지 않으면 자동적으로 getDefaultMiddleware를 사용하지만,
위와같이 작성하면, 기본 middleware에 명시한 middleware를 추가해 사용할 수 있다.


Reference

gitbook-Redux-MiddleWare

벨로퍼트와 함께하는 모던 리액트-미들웨어 만들어보고 이해하기

0개의 댓글