Redux 미들웨어는 Redux Store와 액션 dispatch 사이에 위치하여 액션을 가로채고, 액션이 리듀서에 도달하기 전에 추가적인 작업을 수행할 수 있도록 도와주는 기능이다.
로깅, 충돌 보고, 비동기 API와 통신, 라우팅 등을 위해 Redux 미들웨어를 사용한다.
Redux 미들웨어를 사용하기 위해서는 applyMiddleware 함수를 사용해야한다. 이 함수는 createStore 함수에 인자로 전달되며, 미들웨어 함수들을 조합하여 새로운 함수 체인을 생성한다.
리덕스 미들웨어의 하나로, 액션 객체 대신 함수를 디스패치할 수 있게 해준다.이 함수는 디스패치와 getState 함수를 인자로 받아서, 비동기 작업을 처리하거나 여러 개의 액션을 디스패치할 수 있다.
일반적으로, 액션 생성자 함수는 단순한 객체를 반환하지만 Redux Thunk를 사용하면, 비동기적인 작업을 처리하고 나서 액션 객체를 반환하는 함수를 작성할 수 있다.
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from './reducers';
const store = createStore(
rootReducer,
applyMiddleware(thunk)
);
export default store;
applyMiddleware
함수를 사용하여 thunk
미들웨어를 적용하고, 이를 createStore
함수의 두 번째 인자로 전달하여 스토어를 생성한다.
아래는 redux-think 미들웨어를 이용한 thunk 함수를 사용한 예시이다.
// 액션 타입
export const FETCH_DATA_REQUEST = 'FETCH_DATA_REQUEST';
export const FETCH_DATA_SUCCESS = 'FETCH_DATA_SUCCESS';
export const FETCH_DATA_FAILURE = 'FETCH_DATA_FAILURE';
// 액션 생성자 함수
export const fetchDataRequest = () => ({
type: FETCH_DATA_REQUEST,
});
export const fetchDataSuccess = (data) => ({
type: FETCH_DATA_SUCCESS,
payload: data,
});
export const fetchDataFailure = (error) => ({
type: FETCH_DATA_FAILURE,
payload: error,
});
// thunk 함수
export const fetchData = () => {
return (dispatch) => {
dispatch(fetchDataRequest());
fetch('https://example.com/data')
.then(response => response.json())
.then(data => dispatch(fetchDataSuccess(data)))
.catch(error => dispatch(fetchDataFailure(error)));
};
};
// 리듀서
const initialState = {
loading: false,
data: null,
error: null,
};
const dataReducer = (state = initialState, action) => {
switch (action.type) {
case FETCH_DATA_REQUEST:
return {
...state,
loading: true,
};
case FETCH_DATA_SUCCESS:
return {
...state,
loading: false,
data: action.payload,
};
case FETCH_DATA_FAILURE:
return {
...state,
loading: false,
error: action.payload,
};
default:
return state;
}
};
리덕스 툴킷은 리덕스에서 개발자들이 더 쉽게 상태 관리를 할 수 있도록 도와주는 오픈소스 라이브러리이다.
리덕스를 사용하다 보면 반복적인 코드 작성, 불필요한 보일러플레이트 코드 작성, 불변성 유지에 대한 관리 등 여러 가지 불편함이 있다. 이러한 문제를 해결하기 위해 리덕스 툴킷이 나오게 되었다.
리덕스 툴킷은 다음과 같은 기능을 제공한다.
Immer 라이브러리란?
불변성 유지를 도와주는 JavaSceipr 라이브러리 중 하나이다. Immer를 사용하면 불변성 유지를 위해 번거로운 작업을 수행하지 않아도 되며, 간결하고 직관적인 코드 작성이 가능하다.
Immer는 새로운 객체를 생성하는 대신, 기존 객체를 수정하여 새로운 버전을 생성하는 방식으로 불변성을 유지한다.
예시
import { configureStore, createSlice } from '@reduxjs/toolkit';
const counterSlice = createSlice({
name: 'counter',
initialState: { value: 0 },
reducers: {
increment(state) {
state.value++;
},
decrement(state) {
state.value--;
},
reset(state) {
state.value = 0;
},
incrementByAmount(state, action) {
state.value += action.payload;
},
},
});
const store = configureStore({
reducer: counterSlice.reducer,
});
export const {
increment,
decrement,
reset,
incrementByAmount,
} = counterSlice.actions;
export default store;
위 예시 코드에서는 createSlice()
함수를 사용하여 슬라이스를 정의하고, configueStore()
함수를 사용하여 스토어를 생성합니다. 그리고, createSlice()
함수에서 생성된 액션 생성자 함수들을 바로 내보낸다.
툴킷을 사용하면, 일반적인 리덕스 코드보다 코드량을 대폭 줄일 수 있다. 특히, createSlice()
함수를 사용하면, 액션 타입, 액션 생성자 함수, 리듀서 함수를 한 번에 정의할 수 있다. 또한, configureStore()
함수를 사용하면, 미들웨어 및 DevTools 연동 등의 작섭을 더욱 간단하게 처리할 수 있다.