프로젝트가 복잡해지면 코드가 길어진다. 코드가 길어지면 더 이상 하나의 파일에서 작동 코드와 Redux 관련 코드들을 모두 관리하기가 힘들다.따라서 필요에 따라서 action과 reducer를 분리할 수 있어야 한다.
그런데 Redux 상에서 Reducer는 여러 개가 있을 수가 없다. Reducer는 이미 하나의 함수로 존재하기 때문. 따라서 Redux에서는 여러 개로 나뉜 Reducer를 하나의 함수로 합쳐주는 함수가 존재한다.
이를 해결하기 위한 것이 바로 combineReducers 함수이다. 이 함수는 필요에 따라 Reducer 함수를 여러 개로 나누어 사용하되, 최종적으로는 하나의 Reducer 함수로 합쳐주는 역할을 수행한다.
const { combineReducers } = require('redux');
const userReducer = require('./user');
const postReducer = require('./post');
module.exports = combineReducers({
user: userReducer,
posts: postReducer,
});
(...)
const reducer = require('./reducers');
const store = createStore(reducer);
Redux는 전역 상태 관리 라이브러리로써, 제공해주는 역할도 목적에 맞게 제한되어 있다.
그런데 웹 개발을 수행하면서 필요한 데이터를 비동기 통신 등으로 받아오는 일은 당연히 발생하게 되는데, 일반 Redux에서는 action -> dispatch -> reducer의 작업 순서가 정해져 있어 도중에 비동기 작업을 처리할 수가 없다.
이 문제를 해결하기 위해 개발된 것이 Redux 미들웨어Middleware. 비동기 작업을 처리하기 위한 추가적인 과정이 Redux 작업 순서 사이에 추가되기 때문에 미들웨어라는 명칭이 사용된다.
정확하게 표현하자면, Redux 미들웨어Middleware는 비동기 작업만 가능하게 해주는 역할이 아니다. 기존 Redux에서 할 수 없는 다른 기능을 수행하기 위한 모든 추가 작업들을 미들웨어Middleware라고 부른다.
const thunkMiddleware = (store) => (next) => (action) => {
if (typeof action === 'function') {
return action(store.dispatch, store.getState);
}
return next(action);
};
위 함수는 Redux에서 비동기 통신 작업을 수행할 수 있도록 해주는 대표적인 미들웨어인 Redux-thunk의 코드이다.
Redux-thunk는 dispatch가 호출된 다음, action이 reducer로 넘어가는 과정이 실행되기 전에 제어권을 가져온다. Redux에서 동기 작업은 객체로 처리된다는 특성을 이용하여, 비동기 작업을 함수로 구별한 뒤 함수 내에서 비동기 작업을 수행하고 결과에 따라 적절한 action을 reducer로 돌려준다.
const enhancer = applyMiddleware(thunkMiddleware);
const store = createStore(reducer, enhancer);
이렇게 구현된 thunkMiddleware 함수는 applyMiddleware 함수에 의해 정렬된 다음 createStore 함수의 인자로 reducer와 함께 사용되어 Redux에서 사용이 가능하다.
const thunkMiddleware = (store) => (next) => (action) => {
};
thunkMiddleware 함수는 이상하게도 일반적인 화살표 함수의 문법과 다른 매우 기이한 형태를 띄고 있다.
const func = () => {
};
이런 형태를 바로 고차함수라고 부른다. 고차 함수란 함수 내부에 익명 함수들이 중첩되어 있는 구조를 뜻한다. 함수 선언 문법에서 생략이 가능한 부분들을 생략하다보니 얼핏 보면 저렇게 이해하기 힘든 모양이 만들어지는데 사실 실제로는 이런 모습을 지니고 있다.
const thunkMiddleware = () => {
() => {
() => {
};
};
};
함수 내부에서 익명 함수가 호출되고, 그 내부에서 또 다른 익명 함수가 호출되고 있는 것이다. thunkMiddleware의 경우 사실 인자 3개를 받는 하나의 함수를 사용해도 되지만, 작업 중간에 또 다른 작업을 끼워넣는 미들웨어의 특성상 고차 함수 방식을 사용하면 동작 사이사이의 추가적인 기능을 수행할 수 있기 때문에 저런 방법을 사용하는 것이다.