redux-saga는 애플리케이션의 "부수적인 효과(side effect)"(데이터 요청(fetch) 등의 비동기 작업, 브라우저 캐시 같은 순수하지 않은 것들) 들을 쉽게 관리하고 효과적으로 실행하고 간단한 테스트와 쉬운 실패 처리를 목적으로 한다.
(js에서 side effect는 js코드가 외부세계에 영향을 주거나 받는 것을 의미한다.)
리덕스가 처음 나왔을 때, action creator와 reducer는 순수해야하는데, side effect를 어떻게 처리할 것인가에 대한 물음에서 탄생했다.
Redux-Saga는 애플리케이션에서 필요한 사이드 이펙트를 별도의 스레드로 분리해서 관리할 수 있고, 리덕스의 미들웨어로 리덕스의 액션은 스레드를 시작, 중지, 취소시킬 수 있다.
saga는 generator 함수로 구현된다. promise가 미들웨어에 yield되면, 미들웨어는 promise가 완료될 때까지 saga를 일시 중단한다. promise가 해결되면, 미들웨어는 다시 saga를 다시 시작하여 다음 yield까지 코드를 실행시킨다.
put
: effect의 한 예 / effect는 미들웨어가 수행할 지침들을 포함하는 일반 js객체 / 미들웨어가 saga에 의해 생성된 effect를 검색할 때, saga는 effect가 다 완료될때까지 일시 중단된다.
여러개의 saga를 가지고 있을 때, 그 여러개가 한번에 시작되어야 한다. 이를 위해 rootSaga
를 추가한다.
import { call, put, takeLatest } from 'redux-saga/effects';
import { authActions } from '../reducers/auth.reducer';
import * as authApi from '../../apis/auth.api';
//! call / put
//* call로 api를 호출
//* put으로 dispatch
function* logInSaga(action) {
const { param } = action.payload;
yield put(authActions.setState({ isError: false, showLoginPopup: true }));
try {
yield put(authActions.startRequest());
const member = yield call(authApi.login, 'signin', param);
yield put(authActions.setState({ isLogin: true, member }));
yield put(authActions.setState({ showLoginPopup: false }));
} catch (error) {
console.log(error);
yield put(authActions.setState({ isLogin: false, isError: true }));
} finally {
yield put(authActions.endRequest());
}
}
function* logOutSaga(action) {
const { history } = action.payload;
console.log(history);
yield put(authActions.setState({ isLogin: false, member: [] }));
history.push('/main');
}
//! takeLatest
//* authActions.login 액션 타입일 때, logInSaga를 실행시킨다
export default function* authSaga() {
yield takeLatest(authActions.login, logInSaga);
yield takeLatest(authActions.logout, logOutSaga);
}
thunk : action에 응답을 줄 수 없음
saga : store을 구독하고 특정 작업이 dispatch될 때 saga가 실행되도록 할 수 있음
개발단계부터 배포까지 모든 단계를 자동화를 통해 빠르고 빈번하게 배포하는 것