📦 Redux & Redux Toolkit 완벽 정리
1. Redux의 본질 (왜 쓰는가?)
Redux는 자바스크립트 앱을 위한 **'중앙 집중식 상태 관리 라이브러리'**. 컴포넌트끼리 복잡하게 데이터를 주고받을 필요 없이, 하나의 거대한 창고(Store)에서 모든 상태를 관리
2. 핵심 용어 정리 (4가지 핵심 개념)
이 흐름을 이해하는 것이 가장 중요합니다:
- Store (스토어): 상태가 저장되는 단 하나의 중앙 저장소.
- Action (액션): 상태를 어떻게 변경할지 적어놓은 주문서 (무엇을 할지 type, 어떤 데이터를 보낼지 payload).
- Reducer (리듀서): 주문서(Action)를 보고 실제로 상태를 갈아끼우는 순수 함수.
- Dispatch (디스패치): 주문서(Action)를 스토어에 전달하는 함수.
3. React-Redux (리액트와 연결하기)
Redux는 리액트 전용이 아니기 때문에, 리액트에서 편하게 쓰려면 React-Redux라는 다리가 필요합니다.
- <Provider store={store}>: 리액트 앱 전체에 스토어를 공급합니다.
- useSelector(): 스토어에서 필요한 데이터를 조회할 때 사용합니다.
- useDispatch(): 액션을 발생시켜 데이터를 변경할 때 사용합니다.
4. Redux Toolkit (RTK - 최신 권장 방식)
기존 Redux의 코드가 너무 길고 복잡해서 이를 단순하게 만든 것이 RTK입니다.
- createSlice(): 액션과 리듀서를 한 방에 만듭니다. 이미지 속 설명처럼 스토어를 작은 slice(조각) 단위로 나누어 관리하게 해줍니다.
- configureStore(): 여러 리듀서를 합치고 스토어를 만드는 설정을 아주 단순하게 줄여줍니다.
- createAsyncThunk(): API 호출 같은 비동기 작업을 쉽게 처리하게 돕습니다.
- 1. Redux Toolkit(RTK)이란?
- 목적: 기존 Redux의 복잡한 설정과 반복되는 코드(보일러플레이트)를 줄이기 위해 Redux 팀에서 공식적으로 만든 권장 도구 모음입니다.
- 장점: 설정이 단순하고, 불변성 유지(Immutability) 등을 자동으로 처리해 줍니다.
- configureStore(): 스토어(Store)를 설정하는 함수입니다. 여러 개의 리듀서를 합치거나 미들웨어를 추가하는 작업을 한 번에 처리합니다.
- createSlice(): 가장 중요한 부분입니다. 액션 생성자(Action Creator)와 리듀서(Reducer)를 한 곳에서 동시에 생성합니다. 이미지 속 그림처럼 스토어 안의 작은 조각(Slice)들을 만드는 역할을 합니다.
- createAsyncThunk(): 비동기 작업(API 통신 등)을 처리할 때 사용합니다.
- useSelector(): 스토어에 있는 데이터를 조회(가져오기) 할 때 사용합니다.
- useDispatch(): 액션을 발생시켜 데이터를 변경(업데이트) 요청을 보낼 때 사용합니다.
- 스토어에 저장된 데이터를 가져오거나 변경할 때 다음 두 가지 Hook을 사용합니다.
💡 한 줄 요약 흐름
"RTK(createSlice)로 만든 상태 조각들을 스토어(configureStore)에 모으고, 컴포넌트에서는 useSelector로 읽고 useDispatch로 수정한다!"

app.jsx
import { useDispatch, useSelector } from 'react-redux'
import './App.css'
import { up, down, increamentByNo} from './redux/store'
import Cart from './Cart'
function App() {
const no = useSelector((state)=>{
console.log("----")
console.log(state)
console.log("---")
return state.count.no;
})
const dispatch = useDispatch();
console.log(dispatch)
return (
<>
<h1>React-Redux TEST</h1>
{/* 카운트 UI 영역 */}
<div className="Count">
{/* 버튼 클릭 시 각각 액션을 디스패치 */}
<button onClick={()=>dispatch(down())}>빼기</button>
{/* 현재 Redux store에 저장된 상태 값 표시 */}
<span> {no} </span>
<button onClick={()=>dispatch(up())}>더하기</button>
{/* 5만큼 증가시키는 커스텀 액션 실행 */}
<button onClick={()=>dispatch(increamentByNo())}>5씩 증가</button>
</div>
<hr />
<Cart/>
</>
)
}
export default App
store.jsx
countSlice 선언, cartSlice 선언
import { createSlice, configureStore } from '@reduxjs/toolkit';
//작은 단위(slice )형태로 state 정보를 정의한다.
const countSlice = createSlice({
name: "count",
initialState:{no:0},
reducers: {
up(state){
console.log("up" +state)
state.no = state.no+1;
},
down(state){
console.log("down" + state)
state.no = state.no -1;
},
increamentByNo(state,action){
console.log(state, action)
state.no = state.no +action.payload;
}
}
});
const cartSlice = createSlice({
name: "cart",
initialState:[ {id:1, name:"수박", count:3},
{id:3, name:"딸기", count:5},
{id:2, name:"포도", count:8} ],
reducers:{
addCount(state, action){
let index = state.findIndex((item)=>item.id === action.payload)
state[index].count++;
},
addItem(state, action){
state.push(action.payload);
},
sortByName(state){
state.sort((a,b)=>a.name >b.name ? 1: -1)
}
}
})
export const {up, down, increamentByNo} = countSlice.actions;
export const {addCount, addItem, sortByName} = cartSlice.actions;
export default configureStore({
reducer:{
count : countSlice.reducer,
cart : cartSlice.reducer
}
})
Cart.jsx
import {useDispatch, useSelector} from 'react-redux'
import { sortByName , addCount} from './redux/store';
const Cart = () => {
let state = useSelector((state) => state)
console.log(state.count);
console.log(state.cart[0].name);
// dispatch는 store.js 로 요청보내주는 함수
let dispatch = useDispatch()
return (
<div>
<h5> 장바구니</h5>
<table style={{border:"1px solid red"}}>
<thead>
<tr>
<th>id</th>
<th>상품명</th>
<th>수량</th>
<th>변경하기</th>
</tr>
</thead>
<tbody>
{
state.cart.map((item, i)=>
<tr key={item.id}>
<td>{item.id}</td>
<td>{item.name}</td>
<td>{item.count}</td>
<td><button onClick={()=>dispatch(addCount(item.id))}>+</button></td>
</tr>
)
}
</tbody>
</table>
<br/>
<button onClick={()=>dispatch(sortByName()) }>이름순정렬</button>{' '}
</div>
);
};
export default Cart;
main.jsx
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import './index.css'
import App from './App.jsx'
import {Provider} from 'react-redux';
import store from './redux/store.js';
createRoot(document.getElementById('root')).render(
<Provider store = {store}>
<App />
</Provider>,
)

'Dev > React' 카테고리의 다른 글
| React 개요 및 주요기능 _ 개념 정리 (0) | 2026.04.13 |
|---|---|
| [React Axios] Axios 호출 방법 2가지 | 기본호출, 인스턴스 (0) | 2026.04.09 |
| [React Axios] .then / async-await 함수 비교 실습 (0) | 2026.04.09 |
| [React] fetch + async + await 실습 (1) | 2026.04.09 |
| [React] 비동기 통신 Ajax 이해하기 | Axios 비교 (0) | 2026.04.09 |