터미널에 입력 ... ✍🏻
npm i redux
npm i react-redux
[FLUX 패턴]
UI, Action, Dispatch, Reducer, Store 5가지가 redux의 구성요소

1️⃣ UI
2️⃣ Action
type 속성을 필수적으로 가지고 있으며, 추가적인 데이터를 payload로 전달할 수도 있습니다.//📍 액션 객체(Action Object) 방식
{ type: "INCREMENT", payload: 1 }
{ type: "DECREMENT", payload: 1 }
//📍✨ 액션 생성자(Action Creator) 방식
// 객체를 때마다 만들기 번거롭다 느껴지면 액션 객체를 반환시키는 함수를 사용한다
//payload 값을 동적으로 설정 가능
// payload : 특정한 값을 이용하여 상태를 변경 시키겠다
const incrementAction = {
type: "INCREMENT",
payload: { id }
};
3️⃣ Dispatch
//📍 액션 객체(Action Object) 방식
dispatch({
type: 'INCREMENT'
payload: 5
})
//📍✨ 액션 생성자(Action Creator) 방식
dispatch( increment ( 5 ) )
액션 생성자
4️⃣ Reducer
state 는 상태값 / action은 리듀서로 부터 전달받는 값// state에 설정해주는 초기 값이 상태 저장소를 만들었을 떄 그 상태의 초기값
const counterReducer = (state = { count: 0 }, action) => {
switch (action.type) {
case "INCREMENT":
return { count: state.count + action.payload };
case "DECREMENT":
return { count: state.count - action.payload };
default:
return state;
// 이상한 값이 들어오면 리턴을 받지 못하여 undefind 가 나오기 때문에 기본값을 유지하는 default 값도 작성 필요
}
};
// 🔮 Reducer가 여러 개라면?
// combineReducers 함수로 묶어서 하나로 만들 수 있음
const rootReducer = combineReducers({
counterReducer, anyReducer, ...
})
5️⃣ Store
const store = createStore( rootReducer )
// createStore 가 프로그램에서 취소선으로 막혀 있을 때 legacy_createStore 이걸로 사용하여도 무방
6️⃣ 구성 요소를 다 만들었다면?
React-Redux에서 제공하는 기능을 사용해서
✔️ App과 전역 상태 저장소 연결하기 <Provider store={ store } >
📁 main.jsx
import ReactDOM from 'react-dom/client'
import App from './App.jsx'
import './index.css'
import { BrowserRouter } from 'react-router-dom'
import { Provider } from 'react-redux'
import { store } from './redux/redux.js'
ReactDOM.createRoot(document.getElementById('root')).render(
<BrowserRouter>
<Provider store={store}>
<App />
</Provider>
</BrowserRouter>,
)
✔️ 상태 저장소에서 상태 꺼내서 사용하기 useSelector( )
import { useSelector } from "react-redux";
const CounterDisplay = () => {
// 상태에서 count 값 가져오기
const count = useSelector((state) => state.countReducer);
return <h1>Count: {count}</h1>;
};
✔️ dispatch 함수 만들어서 사용하기 useDispatch( )
import { useDispatch } from "react-redux";
const CounterButton = () => {
const dispatch = useDispatch();
return (
<button onClick={() => dispatch(INCREMENT)}>
증가하기
</button>
);
};
npm i redux react-redux
npm i redux-thunk
1️⃣ store 설정
applyMiddleware를 사용하여 thunk 미들웨어를 적용해야 합니다.import { createStore, applyMiddleware } from "redux";
import thunk from "redux-thunk";
import rootReducer from "./reducers"; // 리듀서
const store = createStore(rootReducer, applyMiddleware(thunk));
export default store;
2️⃣ 사용하기
dispatch((dispatch) => {} ) 공식으로 외우면 됨import { useDispatch } from "react-redux";
const CounterButton = () => {
const dispatch = useDispatch();
return (
<button onClick={() => dispatch((dispatch) => {
setTimeout(() => {
dispatch(INCREMENT)
}, 1000)
)}>
증가하기
</button>
);
};
import { createStore } from "redux";
// 1️⃣ 액션 생성
const INCREMENT = "INCREMENT";
const incrementAction = { type: INCREMENT };
// 2️⃣ 리듀서 함수 정의
const counterReducer = (state = 0, action) => {
switch (action.type) {
case INCREMENT:
return state + 1;
default:
return state;
}
};
// 3️⃣ 스토어 생성
const store = createStore(counterReducer);
// 4️⃣ 상태 변경 감지
store.subscribe(() => console.log("현재 상태:", store.getState()));
// 5️⃣ 액션 디스패치
store.dispatch(incrementAction); // 현재 상태: 1
store.dispatch(incrementAction); // 현재 상태: 2
단일 스토어 (Single Source of Truth)
모든 상태가 하나의 스토어에 저장되므로 상태 관리가 쉬워집니다.
불변성 (Immutability)
상태는 직접 변경할 수 없으며, 새로운 상태 객체를 만들어 교체합니다.
예측 가능성 (Predictability)
상태 변화가 액션을 통해서만 이루어지므로 디버깅이 쉽습니다.
미들웨어 지원 (Middleware)
Redux Thunk, Redux Saga 같은 미들웨어를 사용하면 비동기 작업도 쉽게 처리할 수 있습니다.