누구는 리덕스를 안 쓰는 회사가 없다고 한다.
누구는 리덕스의 러닝커브 때문에 Recoil, Zustand, MobX 사용한다고 한다.
누구는 리액트에서 제공하는 useReducer, context api 조합으로 해도 충분하다고 한다.
의견들이 너무 다양하다... 그냥 다 간단하게라도 개념을 알고, 사용해 보는 경험을 가지는 게 좋을 것 같다.
리덕스(Redux)는 애플리케이션의 상태를 중앙에서 관리하기 위한 JS 라이브러리이다. 주로 React 애플리케이션에서 많이 사용되며, 상태 관리의 복잡성을 줄이고 애플리케이션의 일관성을 유지하는 데 도움이 된다. 하지만 리덕스는 설정이 복잡하고 많은 보일러플레이트 코드가 필요하기 때문에 이를 개선하기 위해 리덕스 툴킷(Redux Toolkit)이 등장했다.
리덕스(Redux)
리덕스는 다음과 같은 주요 개념으로 구성되어 있다.
1. 스토어(store)
- 애플리케이션의 상태가 저장되는 곳이다.
2. 액션(action)
- 상태에 변화를 일으키기 위한 지시사항이다. 주로 객체 형태이며 type 프로퍼티를 가진다.
3. 리듀서(reducer)
- 액션을 처리하여 새로운 상태를 반환하는 함수이다.
4. 디스패치(dispatch)
- 액션을 스토어에 전달하는 함수이다.
리덕스 툴킷(Redux Toolkit)
리덕스 툴킷은 리덕스의 사용을 더 간편하고 효율적으로 만들기 위해 개발된 라이브러리이다. 주요 기능으로는 configureStore, createSlice, createAsyncThunk 등이 있다.
주요 기능
1. configureStore : 스토어 설정을 간편하게 해준다.
2. createSlice : 액션과 리듀서를 한 번에 정의할 수 있게 해 준다.
3. createAsyncThunk : 비동기 액션을 쉽게 생성할 수 있다.
1. 리덕스 툴킷 설치
npm install @reduxjs/toolkit react-redux
2. 스토어 설정
configureStore를 사용하여 스토어를 설정한다.
import { configureStore } from '@reduxjs/toolkit';
import counterReducer from './counterSlice';
const store = configureStore({
reducer: {
counter: counterReducer,
},
});
export default store;
3. 슬라이스(Slice) 생성
createSlice를 사용하여 액션과 리듀서를 한 번에 정의한다.
import { createSlice } from '@reduxjs/toolkit';
const counterSlice = createSlice({
name: 'counter',
initialState: {
value: 0,
},
reducers: {
increment: (state) => {
state.value += 1;
},
decrement: (state) => {
state.value -= 1;
},
incrementByAmount: (state, action) => {
state.value += action.payload;
},
}
});
export const { increment, decrement, incrementByAmount } = counterSlice.actions;
export default counterSlice.reducer;
4. 리액트 컴포넌트에서 사용
리액트 컴포넌트에서 리덕스를 사용하려면 react-redux의 Provider와 useDispatch, useSelector 훅을 사용해야 한다.
import React from 'react';
import { Provider, useDispatch, useSelector } from 'react-redux';
import store from './store';
import { increment, decrement, incrementByAmount } from './counterSlice';
function Counter() {
const dispatch = useDispatch();
const count = useSelector((state) => state.counter.value);
return (
<div>
<div>
<button onClick={() => dispatch(decrement())}>-</button>
<span>{count}</span>
<button onClick={() => dispatch(increment())}>+</button>
</div>
<button onClick={() => dispatch(incrementByAmount(5))}>
Add 5
</button>
</div>
);
}
function App() {
return (
<Provider store={store}>
<Counter />
</Provider>
);
}
export default App;
➕ 리덕스 툴킷에는 몇 가지 주요 라이브러리와 유틸리티가 포함되어 있어 Redux 애플리케이션을 더 쉽게 만들고 관리할 수 있다. 주로 포함되어 있는 라이브러리와 유틸리티는 다음과 같다.
1. immer : 불변성을 쉽게 관리하기 위한 라이브러리.
2. Redux Thunk : 비동기 로직을 처리하기 위한 미들웨어.
3. Reselect : 메모이제이션된 선택자를 만들기 위한 유틸리티.
🚩Immer
Immer는 Redux Toolkit의 내장 라이브러리로, 불변 상태 관리를 더 간단하게 한다. Immer를 사용하면 " draft " 상태를 직접 변경할 수 있으며, Immer가 이를 기반으로 불변 상태를 자동으로 생성해 준다.
const userSlice = createSlice({
name: 'user',
initialState: {
name: 'kim',
age: 20,
},
reducers: {
changeName(state) {
state.name = '설민'; // Immer 덕분에 불변 상태를 신경 쓰지 않아도 됨
},
plusAge(state, action) {
state.age += action.payload; // 마찬가지로 불변 상태를 쉽게 변경 가능
},
},
});
왜 포함되어 있는가?
- 불변성 유지 : 불변 상태 관리는 Redux의 핵심 원칙 중 하나이다. Immer는 이를 쉽게 유지할 수 있게 도와준다.
- 코드 간결성 : 불변 상태 관리를 직접 구현하는 것보다 코드를 더 간결하게 만들어준다.
🚩Redux Thunk
Redux Thunk는 Redux 애플리케이션에서 비동기 로직(예:API 호출)을 처리하는 데 사용되는 미들웨어이다. Thunk는 액션 생성자가 함수를 반환할 수 있게 해 준다. 이 함수는 ` dispatch ` 와 ` getState `를 인자로 받아서 비동기 작업을 수행한 후 필요한 액션을 디스패치한다.
import { createAsyncThunk } from '@reduxjs/toolkit';
import axios from 'axios';
export const fetchUser = createAsyncThunk(
'user/fetchUser',
async (userId, thunkAPI) => {
const response = await axios.get(`/api/users/${userId}`);
return response.data;
}
);
const userSlice = createSlice({
name: 'user',
initialState: {
name: 'kim',
age: 20,
status: 'idle',
error: null,
},
reducers: {
// 동기적 리듀서들
},
extraReducers: (builder) => {
builder
.addCase(fetchUser.pending, (state) => {
state.status = 'loading';
})
.addCase(fetchUser.fulfilled, (state, action) => {
state.status = 'succeeded';
state.name = action.payload.name;
state.age = action.payload.age;
})
.addCase(fetchUser.rejected, (state, action) => {
state.status = 'failed';
state.error = action.error.message;
});
},
});
왜 포함되어 있는가?
- 비동기 로직 처리 : Redux는 기본적으로 동기적인 상태 관리 라이브러리이다. Thunk를 사용하면 비동기 작업을 처리할 수 있다.
- 간단한 미들웨어 : Thunk는 비교적 간단한 미들웨어로, 추가적인 설정 없이 바로 사용할 수 있다.
🚩Reselect
Reselect는 Redux 상태에서 파생된 데이터를 메모이제이션하여 캐싱할 수 있는 유틸리티이다. 메모이제이션을 통해 불필요한 리렌더링을 줄이고 성능을 최적화할 수 있다.
import { createSelector } from 'reselect';
const selectCartItems = (state) => state.cartItem;
const selectCartTotal = createSelector(
[selectCartItems],
(cartItems) =>
cartItems.reduce((total, item) => total + item.count, 0)
);
왜 포함되어 있는가?
- 성능 최적화 : 불필요한 리렌더링을 줄여 성능을 최적화할 수 있다.
- 간결한 코드 : 파생된 데이터를 간결하게 계산할 수 있다.
'React' 카테고리의 다른 글
리액트의 동작원리 TEST (0) | 2024.07.02 |
---|---|
리덕스 툴킷을 사용해보자. (0) | 2024.06.26 |
useLayoutEffect + useEffect, useTransition, useDeferredValue (0) | 2024.06.20 |
useState 사용할 때 함수설정 (0) | 2024.06.17 |
[Webpack]를 수동으로 설정해보기 (3) (0) | 2024.06.17 |