리액트 프로젝트의 state 관리 생태계가 리덕스 독점 체제에서
새로운 혁신적인 state 관리 라이브러리들의 등장과 함께 파이가 줄어들고 있는 것은 사실이지만 아직까지도 리덕스의 위엄은 인정할 만 하다.
솔직히 코린이가 새롭고 혁신적인 라이브러리를 배워봤자 처음 접하는 기술 스택은 말로 형용할 수 없는 현타를 느낄 것이기에 일단 하나라도 제대로 파보자!
리덕스도 날것의 리덕스 문법을 맛있게 요리해 먹을 수 있는 라이브러리가 존재한다.
대표적으로 redux-thunk
와 redux-saga
가 있는데 오늘은 리덕스 사가를 살펴 보겠다.
그래서 리덕스 사가가 무엇인가?
공식 문서에 따르면, 리액트/리덕스 애플리케이션의 사이드 이펙트를 더 쉽고 좋게 만드는 것을 목적으로 하는 미들웨어 라이브러리라고 정의하고 있다.
(꼬리물기의 연속)
그렇다면 사이드 이펙트는 무엇인가?
언어적으로 side effect는 부작용을 의미한다.
반면에, 프로그래밍에서는 하나의 이펙트가 발생할 때 다른 이펙트가 함께 발생하는 현상을 말한다. 프로그램에서 말하는 이펙트는 함수의 작동으로 생각할 수 있겠다.
어떻게 보면 부작용이라는 언어적 의미와 유사성을 찾을 수 있다.
하지만, 이런 사이드 이펙트가 무조건 나쁘지도 좋지도 않은 것이 프로그램에서의 현실이다.
이렇게 리덕스 사가가 사이드 이펙트를 효율적으로 관리 할 수 있다는것을 살펴봤는데 구체적으로 어떤 부분이 있을까?
이외에도 다른 부분들에서도 사가의 효율성을 발견할 수 있겠지만 뇌 용량의 한계가 있기 때문에 추후에 추가적으로 살펴보겠다.
redux-saga에서는 액션 타입, 액션 크리에이터 함수, 리듀서 함수 외에 사가 함수를 만들어야 한다.
사가 함수는 액션 객체를 모니터링하면서 액션 객첵의 타입이 변하면 액션 타입이 일치하는 사가 함수를 실행한다.
import { call, put, takeEvery, takeLatest } from 'redux-saga/effects'
import Api from '...'
// worker Saga: USER_FETCH_REQUESTED 액션에 대해 호출될 것입니다
function* fetchUser(action) {
try {
const user = yield call(Api.fetchUser, action.payload.userId);
yield put({type: "USER_FETCH_SUCCEEDED", user: user});
} catch (e) {
yield put({type: "USER_FETCH_FAILED", message: e.message});
}
}
/*
각각의 dispatch 된 `USER_FETCH_REQUESTED` 액션에 대해 fetchUser를 실행합니다.
동시에 user를 fetch하는 것을 허용합니다.
*/
function* mySaga() {
yield takeEvery("USER_FETCH_REQUESTED", fetchUser);
}
/*
또는 takeLatest를 사용할 수 있습니다.
동시에 user를 fetch하는 것을 허용하지 않습니다. 만약 fetch가 이미 대기 상태일 때 "USER_FETCH_REQUESTED"가 dispatch가 되었다면 대기 상태의 fetch는 취소되고 항상 최근 것만이 실행됩니다.
*/
function* mySaga() {
yield takeLatest("USER_FETCH_REQUESTED", fetchUser);
}
export default mySaga;
다음 공식 문서 예제 코드를 처음 마주 했을 때, 정말 이걸 공부해야되나 싶었다.
일단 나를 망설이게 했던건 yield
라는 키워드였다.
위치 상으로 생각해보면 return
과 비슷한 역할을 담당한다고 생각되는데, 변수에 할당할 때도 사용하고 이펙트 함수를 실행할 때도 사용하니 머리가 아파왔다.
MDN 공식문서에 따르면 yield
는 generator
함수나 iterable
객체를 위임할 때 사용한다는데 자세한 내용은 링크를 참조하길,,
다음으로 살펴볼 것은 사가에서 제공되는 이펙트 함수를 살펴 보자.
이 여섯가지 외에도 다양한 함수를 제공하지만 나머지는 공식문서로 yield
하겠다.