미들웨어란?
액션 디스패치를 했을 때 리듀서에 이를 처리하기 앞서 사전에 지정된 작업을 실행한다.
미들웨어는 액션과 리듀서 사이의 중간자라 생각하면 쉽다.
미들웨어의 용도
- 특정 조건에 따라 액션을 무시
- 특정 조건에 따라 액션 정보를 가로채 변경한 후 리듀서에 전달
- 특정 액션에 기반하여 새로운 액션을 여러번 디스패치
- 전달받은 액션을 콘솔에 기록
- 전달받은 액션 정보를 기반으로 액션을 취소
- 다른 종류의 액션을 추가로 디스패치
미들웨어의 기본 구조
const loggerMiddleWare = store => next => action{
// 미들웨어 기본 구조
};
export default loggerMiddleWare;
store는 리덕스 스토어 인스턴스를 가르키고, action은 디스패치된 액션을 가르킨다.
next는 파라미터 함수 형태이며, next(action)을 호출하면 그 다음 처리해야 할 미들웨어에게 액션을 넘겨주고,
그 다음 미들웨어가 없다면 리듀서에게 액션을 넘겨준다.
작업 환경 설정
CRA를 사용해 새 리액트 프로젝트를 생성하자
modules/counter.js
import { createAction, handleActions } from 'redux-actions';
const INCREASE = 'counter/INCREASE';
const DECREASE = 'counter/DECREASE';
export const increase = createAction(INCREASE);
export const decrease = createAction(DECREASE);
const initialState = 0; // 상태는 객체일 필요가 없고 숫자로도 동작 가능하다.
const counter = handleActions(
{
[INCREASE]: state => state + 1,
[DECREASE]: state => state - 1,
},
initialState
);
export default counter;
modules/index.js
import { combineReducers } from 'redux';
import counter from './counter';
const rootReducer = combineReducers({
counter
})
export default rootReducer;
index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import { configureStore } from '@reduxjs/toolkit';
import { Provider } from 'react-redux';
import App from './App';
import reportWebVitals from './reportWebVitals';
import rootReducer from './modules';
const root = ReactDOM.createRoot(document.getElementById('root'));
const store = configureStore({
reducer: rootReducer
});
root.render(
<Provider store={store}>
<App />
</Provider>
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
components/Counter.js
const Counter = ({ onIncrease, onDecrease, number }) => {
return (
<div>
<h1>{number}</h1>
<button onClick={onIncrease}>+1</button>
<button onClick={onDecrease}>-1</button>
</div>
);
};
export default Counter;
containers/CounterContainer.js
import { connect } from 'react-redux';
import { increase, decrease } from '../modules/counter';
import Counter from '../component/Counter';
const CounterContainer = ({ number, increase, decrease }) => {
return (
<Counter number={number} onIncrease={increase} onDecrease={decrease} />
);
};
export default connect(
state => ({
number: state.counter
}),
{
increase,
decrease
}
)(CounterContainer);
App.js
import CounterContainer from './container/CounterContainer'
const App = () => {
return (
<div>
<CounterContainer />
</div>
);
}
export default App;
미들웨어 만들기, 적용하기
미들웨어는 직접 만들어 사용할 경우는 많이 없다.
대부분의 경우에는 다른 개발자가 만들어 놓은 미들웨어를 사용하면 된다.
하지만, 원하는 미들웨어를 찾을 수 없을 때는 만들거나 커스터 마이징 해야하기에 미들웨어를 만들어 보자
만들어볼 미들웨어는 정보를 순차적으로 콘솔에 보여주도록 만들어보자
- 이전 상태
- 액션 정보
- 새로워진 상태
위의 순서대로 해당하는 정보를 전달하도록 코드를 작성해 보자.
loggerMiddleware.js
const loggerMiddleware = store => next => action => {
console.group(action && action.type); // 액션 타입으로 log를 그룹화함
console.log('이전 상태', store.getState());
console.log('액션', action);
next(action); // 다음 미들웨어 혹은 리듀서에게 전달
console.log('다음 상태', store.getState()); // 업데이트된 상태
console.groupEnd(); // 그룹 끝
};
export default loggerMiddleware;
index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import { configureStore } from '@reduxjs/toolkit';
import { Provider } from 'react-redux';
import App from './App';
import reportWebVitals from './reportWebVitals';
import rootReducer from './modules';
import loggerMiddleware from './lib/loggerMiddleware';
import { createLogger } from 'redux-logger';
const root = ReactDOM.createRoot(document.getElementById('root'));
const logger = createLogger();
const store = configureStore({
reducer: rootReducer,
middleware: [loggerMiddleware],
});
root.render(
<Provider store={store}>
<App />
</Provider>
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
미들웨어를 만들어 봤는데, 매번 사용할 때 작업에 맞는 미들웨어를 작성하기에는 복잡하다.
그래서!!
다른 개발자가 만들어 놓은 미들웨어를 사용해보자!
우선 redux-logger 미들웨어를 설치해보자 (redux-logger는 먼저 만들 미들웨어와 같은 동작을 한다)
npm add redux-logger
설치 후 index.js를 수정하자
import React from 'react';
import ReactDOM from 'react-dom/client';
import { configureStore } from '@reduxjs/toolkit';
import { Provider } from 'react-redux';
import App from './App';
import reportWebVitals from './reportWebVitals';
import rootReducer from './modules';
// import loggerMiddleware from './lib/loggerMiddleware';
import { createLogger } from 'redux-logger';
const root = ReactDOM.createRoot(document.getElementById('root'));
const logger = createLogger();
const store = configureStore({
reducer: rootReducer,
middleware: [logger],
});
root.render(
<Provider store={store}>
<App />
</Provider>
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
지금까지 미들웨어의 기초와 logger 미들웨어를 만들어보고 적용하고, 만들어진 미들웨어를
적용해보았다.
다음 게시글은 비동기 작업을 처리하는 redux-thunk를 다뤄보자.
'React' 카테고리의 다른 글
React) 18장 리덕스 미들웨어를 이용한 비동기 작업관리 ( redux-saga ) (0) | 2022.05.21 |
---|---|
React) 18장 리덕스 미들웨어를 이용한 비동기 작업관리 ( Thunk ) (0) | 2022.05.20 |
React) 17장 리덕스를 이용한 Todo리스트 (0) | 2022.05.14 |
React) 16장 redux 라이브러리 (0) | 2022.05.12 |
React) 15장 Context API (0) | 2022.05.11 |