이번 포스팅에서는 리덕스의 비동기적인 작업의 처리하는 방법 중 Thunk 미들웨어에 대해서 정리하겠습니다.
redux-thunk는 리덕스를 사용하는 프로젝트에서 비동기 작업을 처리할 대 가장 기본적으로 사용되는 미들웨어입니다. 이 라이브러리를 이해하기 위해서는 Thunk에 대해서 이해해야합니다.
thunk는 특정 작업을 나중에 할 수 있도록 미루기 위해 함수 형태로 감싼 것을 의미합니다.
cosnt addOne = x => x+1;
addOne(10); // 11
예시로, 전달받은 숫자에 1을 더해주는 함수가 있습니다. 이 연산작업을 미루기 위해서 thunk를 사용할 수 있습니다. 여기서, Thunk 함수는 숫자를 입력받아 addOne 함수를 호출하는 함수를 리턴하는 함수입니다.
cosnt addOne = x => x+1;
const addOneThunk = x => () => addOne(x); // Thunk 함수는 addOne을 호출하는 함수를 리턴합니다.
}
const fn = addOneThunk(10);
setTimeout(()=> { // 2초 후에 addOneThunk(10) 호출한 결과를 콘솔에 출력합니다.
const value = fn(); // 최종적으로, addOne(10) 호출된 결과가 콘솔에 출력됩니다.
console.log(value);
}, 2000)
redux-thunk 라이브러리는 thunk 함수를 만들어서 디스패치할 수 있습니다. 그 후에 리덕스 미들웨어가 그 미들웨어가 그 함수를 전달받아 store의 dispatch와 getState를 파라미터로 넣어서 호출해 줍니다.
redux-thunk의 코드를 간단하게 나타내면 기본적으로 아래와 같습니다. 액션 객체 대신 함수를 반환합니다.
const thunk = store => next => action =>
typeof action === 'function'
? action(store.dispatch, store.getState) // 액션이 함수인 경우 dispatch, getState 사용이 가능한 함수를 리턴합니다.
: next(action) // 액션이 함수가 아닌 경우 다음 미들웨어 또는 리듀서로 액션값을 전달합니다.
액션으로 객체가 아니라 함수가 들어올 경우에 그 함수에 store 인스턴스의 dispatch와 getState 함수를 전달하여 호출하게 됩니다. 즉, action이 함수인 경우, 함수 내부에서 dispatch, getState를 사용하여 state값을 조작하는 로직을 작성할 수 있습니다.
쉽게 접할 수 있는 예제로 클릭 시 숫자가 1씩 증가하거나 감소하는 counter를 예시로 코드를 작성하겠습니다. redux-actions 라이브러리를 이용해서 액션과 리듀서를 정의합니다.
// 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);
export const increaseAsync = () => dispatch => {
setTimeout(() => { // 1초 후에 type이 'counter/INCREASE'인 객체를 디스패치합니다.
dispatch(increase());
}, 1000)
};
export const decreaseAsync = () => dispatch => {
setTimeout(() => { // 1초 후에 type이 'counter/DECREASE'인 객체를 디스패치합니다.
dispatch(decrease());
}, 1000)
};
const initialState = 0;
const counter = handleActions( // handleActions로 리듀서 생성합니다.
{
[INCREASE] : state => state + 1,
[DECREASE] : state => state - 1
},
initialState
);
export default counter;
thunk 미들웨어만 존재한다는 가정하에 increaseAsync의 비동기 작업의 순서를 정리하면,
thunk 함수가 무엇인지와 비동기적 작업 처리 시 redux-thunk 미들웨어의 역할에 대해서 정리해보았습니다. 내용들을 정리하면서 리덕스에서 미들웨어 편의성과 작업 처리방식과 흐름에 대해 이해할 수 있게 되었습니다. 미들웨어 개념이 리덕스를 처음 사용하는 사람에게는 진입장벽이 될 수도 있겠지만 익숙해진다면 굉장히 유용한 도구가 될 것이라는 생각이 들었습니다. 다음에는 더 까다로운 상황에 적용할 수 있는 redux-saga 미들웨어에 대해서 다뤄볼까 합니다.
길벗 출판사, 리액트를 다루는 기술