Redux는 복잡한 상태 관리를 단순화하고 체계적으로 관리할 수 있도록 도와주는 JavaScript 상태 관리 라이브러리입니다. 이 글에서는 Redux와 Redux Toolkit을 활용하여 리액트 애플리케이션에서 전역 상태를 관리하는 방법에 대해 설명하겠습니다.
Redux는 주로 React와 함께 사용되는 상태 관리 라이브러리로, 애플리케이션의 전역 상태를 예측 가능하게 관리할 수 있도록 설계되었습니다. Redux는 상태를 단일 저장소(Store)에 보관하고, 컴포넌트 간 상태의 일관성을 유지하면서 쉽게 상태를 업데이트할 수 있게 도와줍니다.
Redux의 데이터 흐름은 단방향 데이터 흐름을 따르며, 이를 통해 애플리케이션의 상태 관리가 명확해지고 디버깅이 쉬워집니다.
Redux의 데이터 흐름은 Flux 패턴을 기반으로 하고 있습니다. Flux 패턴은 데이터의 흐름을 단방향으로 정의하여 복잡한 상태 변경을 쉽게 추적할 수 있도록 합니다.
// Action 정의
const INCREMENT = 'INCREMENT';
const incrementAction = () => ({ type: INCREMENT });
// Reducer 정의
const initialState = { count: 0 };
const counterReducer = (state = initialState, action) => {
switch (action.type) {
case INCREMENT:
return { ...state, count: state.count + 1 };
default:
return state;
}
};
// Store 생성
import { createStore } from 'redux';
const store = createStore(counterReducer);
// Dispatch 사용
store.dispatch(incrementAction());
console.log(store.getState()); // { count: 1 }
import React from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { incrementAction } from './actions';
const CounterComponent = () => {
const dispatch = useDispatch();
const count = useSelector((state) => state.count);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => dispatch(incrementAction())}>Increment</button>
</div>
);
};
Redux Thunk는 Redux에서 비동기 작업을 수행할 수 있게 해주는 미들웨어입니다. 기본적으로 Redux는 동기적인 상태 업데이트만 허용하지만, Thunk를 사용하면 API 호출과 같은 비동기 작업을 액션으로 처리할 수 있습니다.
const fetchData = () => {
return async (dispatch) => {
const response = await fetch('https://api.example.com/data');
const data = await response.json();
dispatch({ type: 'FETCH_DATA_SUCCESS', payload: data });
};
};
Redux Toolkit은 Redux를 더 쉽고 간단하게 사용할 수 있도록 도와주는 공식 툴입니다. 보일러플레이트 코드를 줄여주고, 간결한 API를 제공하여 Redux의 복잡함을 해결해줍니다.
Redux Toolkit은 Redux 애플리케이션 개발을 단순화하고 생산성을 높이기 위해 만들어진 도구입니다. 기존 Redux의 복잡한 설정을 간소화하고, 쉽게 상태 관리를 구현할 수 있게 도와줍니다.
createSlice
와 configureStore
같은 유틸리티를 사용하여 더 간단하게 상태와 스토어를 설정할 수 있습니다.import { createSlice, configureStore } from '@reduxjs/toolkit';
// Slice 생성
const counterSlice = createSlice({
name: 'counter',
initialState: { count: 0 },
reducers: {
increment: (state) => {
state.count += 1;
},
},
});
export const { increment } = counterSlice.actions;
// Store 생성
const store = configureStore({
reducer: {
counter: counterSlice.reducer,
},
});
export default store;
Redux Toolkit에서는 비동기 작업을 보다 쉽게 관리하기 위해 createAsyncThunk()를 제공합니다. 이를 사용하면 비동기 액션을 간편하게 작성할 수 있습니다.
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
// Thunk 생성
export const fetchUserData = createAsyncThunk(
'user/fetchUserData',
async (userId) => {
const response = await fetch(`https://api.example.com/users/${userId}`);
return response.json();
}
);
// Slice 생성
const userSlice = createSlice({
name: 'user',
initialState: { data: null, loading: false },
reducers: {},
extraReducers: (builder) => {
builder
.addCase(fetchUserData.pending, (state) => {
state.loading = true;
})
.addCase(fetchUserData.fulfilled, (state, action) => {
state.loading = false;
state.data = action.payload;
})
.addCase(fetchUserData.rejected, (state) => {
state.loading = false;
});
},
});
export default userSlice.reducer;
Redux와 Redux Toolkit을 사용하면 React 애플리케이션에서 전역 상태를 체계적으로 관리할 수 있습니다. Redux는 상태 관리의 복잡성을 해결하는데 매우 유용하지만, 코드가 복잡해질 수 있다는 단점이 있습니다. 반면 Redux Toolkit은 이러한 복잡성을 해결하고 개발을 더 쉽게 만들어줍니다. 전역 상태 관리가 필요할 때, Redux와 Redux Toolkit을 비교하여 적합한 도구를 선택해 보세요.