redux-saga 미들웨어는 Generator 문법을 사용해서 비동기 처리를 관리해줍니다. 그러므로 미들웨어를 공부하기 전에 발생자에 대한 문법과 개념을 알아두어야합니다. 발생자 문법과 설명은 발생자 포스트를 참조해주세요.
redux-thunk에 이어서 또 다른 비동기 처리
를 담당하는 리덕스 미들웨어 redux-saga
를 알아보겠습니다.
yarn
을 통해 redux-saga
를 설치해주세요.
yarn add redux-saga
redux-thunk에서 사용했던 ColorChanger 앱을 redux-saga
를 적용시킨 어플리케이션으로 변경해보겠습니다.
우선 modules의 코드에서 액션, 액션 생성 함수를 다시 정의하고 제너레이터까지 만들어보겠습니다.
import {createAction, handleActions} from 'redux-actions';
import {delay, put, takeEvery} from 'redux-saga/effects';
const SET_COLOR_BLACK = 'colorChangerMW/SET_COLOR_BLACK';
const SET_COLOR_BLUE = 'colorChangerMW/SET_COLOR_BLUE';
const SET_COLOR_RED = 'colorChangerMW/SET_COLOR_RED';
const SET_COLOR_BLACK_ASYNC = 'colorChangerMW/SET_COLOR_BLACK_ASYNC';
const SET_COLOR_BLUE_ASYNC = 'colorChangerMW/SET_COLOR_BLUE_ASYNC';
const SET_COLOR_RED_ASYNC = 'colorChangerMW/SET_COLOR_RED_ASYNC';
export const setColorBlack = createAction(SET_COLOR_BLACK);
export const setColorBlue = createAction(SET_COLOR_BLUE);
export const setColorRed = createAction(SET_COLOR_RED);
//두 번째 인자의 함수는 클릭 이벤트가 payload에 들어가는 것을 막기 위함!
export const setColorBlackAsync = createAction(SET_COLOR_BLACK_ASYNC, () => undefined);
export const setColorBlueAsync = createAction(SET_COLOR_BLUE_ASYNC, () => undefined);
export const setColorRedAsync = createAction(SET_COLOR_RED_ASYNC, () => undefined);
function* setColorBlackSaga() {
yield delay(1000);
yield put(setColorBlack()); //액션 디스패치
}
function* setColorBlueSaga() {
yield delay(1000);
yield put(setColorBlue());
}
function* setColorRedSaga() {
yield delay(1000);
yield put(setColorRed());
}
export function* colorChangerSaga() {
//takeEvery: 모든 액션에 대해 작업 처리
yield takeEvery(SET_COLOR_BLACK_ASYNC, setColorBlackSaga);
yield takeEvery(SET_COLOR_BLUE_ASYNC, setColorBlueSaga);
yield takeEvery(SET_COLOR_RED_ASYNC, setColorRedSaga);
}
const initialState = {
text: '검정',
color: '#000',
};
const colorChangerMW = handleActions(
{
[SET_COLOR_BLACK]: (state, action) => ({
text: '검정',
color: '#000',
}),
[SET_COLOR_BLUE]: (state, action) => ({
text: '파랑',
color: '#00f',
}),
[SET_COLOR_RED]: (state, action) => ({
text: '빨강',
color: '#f00',
}),
},
initialState
);
export default colorChangerMW;
다음으로는 modules/index.js에서 루트 사가(Root Saga)
를 만들어 줍니다. 루트 사가
는 루트 리듀서 처럼 여러 개의 사가들을 하나로 묶는 역할을 해줍니다.
import {combineReducers} from 'redux';
import {all} from 'redux-saga/effects';
import colorChangerMW, {colorChangerSaga} from './colorChangerMW';
const rootReducer = combineReducers({
colorChangerMW,
});
//루트 사가
export function* rootSaga() {
//all은 Saga들을 합쳐줍니다.
yield all([colorChangerSaga()]);
}
export default rootReducer;
여기까지 완료되었다면, src/index.js에서 스토어를 수정해주어야합니다.
// ...이상 import문 생략
import createSagaMiddleWare from 'redux-saga';
const logger = createLogger();
const sagaMiddleware = createSagaMiddleWare();
const store = createStore(rootReducer, applyMiddleware(logger, ReduxThunk, sagaMiddleware));
sagaMiddleware.run(rootSaga);
ReactDom.render(
<Provider store={store}>
<App/>
</Provider>,
document.getElementById('root'),
);
App.js를 실행했을 때 1초 뒤에 글자와 색상이 변경되면 올바르게 처리한 것 입니다. 그리고 개발자 도구를 열어 redux-logger로 log를 살펴볼 때 입력한 대로, 변하는대로 액션이 디스패치 되었나요?