일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 |
- cloud hsm
- rust 기초
- vue기초
- 오블완
- erc4337
- redux 기초
- ethers typescript
- 러스트 기초
- SBT표준
- redux toolkit 설명
- 러스트기초
- 러스트 기초 학습
- 스마트컨트렉트 함수이름 중복 호출
- 머신러닝기초
- cloud hsm 서명
- ethers type
- 스마트컨트렉트 예약어 함수이름 중복
- cloud hsm 사용하기
- git rebase
- 체인의정석
- ethers websocket
- Vue.js
- 컨트렉트 동일한 함수이름 호출
- 계정추상화
- 티스토리챌린지
- ambiguous function description
- erc4337 contract
- 스마트 컨트렉트 함수이름 중복
- ethers v6
- Vue
- Today
- Total
체인의정석
Redux 기초개념 부터 기본 예제까지 정리 ( useDispatch, useSelector ,사용법) 본문
인계를 받을 코드가 Redux위주로 작성되어 있어서 정리를 하였다.
Redux에 대한 기초지식이 없는 상황에서 빠르게 기본틀을 살펴보는것을 목적으로 지피티에게 기본 예제를 생성해서 분석해보았다.
0. REDUX 기초 개념
=> 여러 페이지에서 공통적으로 사용되는 저장소 같은 개념,
1. Store (저장소)
- 앱의 전체 상태(state)를 담고 있는 객체입니다.
- 하나의 애플리케이션에는 하나의 Store만 존재합니다.
2. Action (행동)
- 상태를 어떻게 바꿀 것인지를 설명하는 객체입니다.
- 필수 속성: type (문자열)
{ type: "INCREMENT" }
3. Reducer (감소기)
- 기존 상태(state)와 action을 받아서, 새로운 상태를 반환하는 순수 함수입니다.
- 상태의 변화는 여기에서 정의됩니다.
function counter(state = 0, action) {
switch (action.type) {
case "INCREMENT":
return state + 1;
case "DECREMENT":
return state - 1;
default:
return state;
}
}
4. Dispatch (발송)
- action을 reducer로 전달하는 함수입니다.
store.dispatch({ type: "INCREMENT" });
5. 🔄 Redux 흐름
사용자 인터랙션
↓
Action 생성
↓
dispatch(Action)
↓
Reducer가 Action 수신
↓
새로운 State 반환
↓
Store가 State 갱신
↓
UI가 변경됨
🔧 왜 Redux를 쓸까?
✅ 장점
- 상태를 중앙 집중화 → 컴포넌트 간 상태 공유가 쉬움
- 예측 가능한 상태 변화 → 디버깅 용이
- 미들웨어 확장성 → redux-thunk, redux-saga 등
❌ 단점
- 보일러플레이트(코드 양) 많음
- 간단한 앱에는 과도한 도입일 수 있음
- React Context API로 대체 가능한 경우도 많음
1. 핵심 함수
useDispatch
useDispatch는 redux 스토어에 액션을 보내는 함수를 반환하고 useSelector는 redux 스토어의 상태를 가져오는 훅이다.
useDispatch
- 상태를 변경하는 액션을 발생시킵니다
- 비동기 작업(API 호출 등)을 처리할 수 있습니다
- Redux 미들웨어와 함께 사용됩니다
예시)
import { useDispatch } from 'react-redux';
import { fetchUser } from './userSlice'; // thunk 함수 혹은 action creator
function MyComponent() {
const dispatch = useDispatch();
const handleClick = () => {
dispatch(fetchUser()); // 액션 디스패치
};
return <button onClick={handleClick}>유저 불러오기</button>;
}
위의 예시에서 useDispatch는 Redux액션 수행을 위한 hook으로 작동하며 dispatch(fetchUser())를 하면 실제로 서버에 요청을 보내고 redux 상태를 자동으로 갱신 시킨다.
또한 엑셀과 같이 데이터를 내보낼 때는 dispatch(export(...))와 같이 사용하면 엑셀로 파일 export를 손쉽게 할 수 있다.
useSelector
- 상태를 구독하고 변경사항을 감지합니다
- 필요한 상태만 선택적으로 가져올 수 있습니다
- 컴포넌트 리렌더링 최적화에 도움이 됩니다
useSelector를 쓰면 ReduxStore의 rootState에서 데이터를 가져올 수 있다.
useSelector에서 아이템을 가져와서 컴포넌트 UI에 뿌려지는 식으로 구현이 가능하다.
예시)
예를 들어 Redux에서
// Redux slice 예시
const initialState = { value: 0 };
const counterSlice = createSlice({
name: 'counter',
initialState,
reducers: {
increment: (state) => {
state.value += 1;
},
},
});
export const { increment } = counterSlice.actions;
export default counterSlice.reducer;
위와 같이 counter라는 이름의 변수가 관리되고 있다면
import { useSelector } from 'react-redux';
const MyComponent = () => {
const counter = useSelector((state) => state.counter.value);
return <div>현재 카운트: {counter}</div>;
};
위와 같이 UseSelector를 통해서 state.counter를 통해서 해당 counter 변수의 value를 불러와서 사용할 수 있게 된다.
🔒 주의점
- useSelector는 필요한 값만 가져와야 합니다.
전체 state를 다 가져오면 성능 저하가 발생할 수 있어요. - 불필요한 리렌더링 방지
값이 바뀌지 않았는데도 리렌더링 되는 걸 막으려면 useMemo, shallowEqual 등을 활용하기도 합니다:
import { shallowEqual, useSelector } from 'react-redux';
const user = useSelector(
(state) => ({
name: state.user.name,
email: state.user.email,
}),
shallowEqual
);
2. 기본예제
위의 개념을 적용한 간단한 카운터앱 예제를 살펴보았다.
📁 폴더 구조 예시
/src
├── /app
│ └── store.js
├── /features
│ └── counterSlice.js
└── App.jsx
1️⃣ store.js – Redux store 설정
// src/app/store.js
import { configureStore } from '@reduxjs/toolkit';
import counterReducer from '../features/counterSlice';
export const store = configureStore({
reducer: {
counter: counterReducer,
},
});
위와 같이 reduxStore를 설정한 후 reducer를 설정해둔다.
내가 보고 있는 프로젝트에서는 configureStore안에 rootReducer를 따로 만들어 두어서 해당 Reducer안에 각 테이블별로 Slice가 들어가 있다. API 호출 및 엑셀시트 기본 틀 또한 reducer안에 들어가 있었다.
2️⃣ counterSlice.js – 상태 + 액션 정의
// src/features/counterSlice.js
import { createSlice } from '@reduxjs/toolkit';
const initialState = {
value: 0,
};
export const counterSlice = createSlice({
name: 'counter',
initialState,
reducers: {
increment: (state) => {
state.value += 1;
},
decrement: (state) => {
state.value -= 1;
},
reset: (state) => {
state.value = 0;
},
},
});
export const { increment, decrement, reset } = counterSlice.actions;
export default counterSlice.reducer;
여기서는 상태와 액션을 정의해주는 부분이 들어가게 된다. counterReducer를 정의하였는데 상황에 따라서 여기서 api에 대한 호출, 응답 후 각 state에 대한 업데이트를 해주는 로직이 들어가게 된다.
이렇게 counterSlice.reducer를 기본값(default) 으로 export했기 때문에,
다른 파일에서 import할 때는 원하는 이름으로 불러 올 수 있어 counterReducer라는 이름으로 사용중이다.
3️⃣ App.jsx – useSelector + useDispatch 사용
// src/App.jsx
import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { increment, decrement, reset } from './features/counterSlice';
function App() {
const count = useSelector((state) => state.counter.value); // Redux 상태 가져오기
const dispatch = useDispatch(); // 액션 디스패치 함수
return (
<div style={{ textAlign: 'center', marginTop: '100px' }}>
<h1>카운터: {count}</h1>
<button onClick={() => dispatch(increment())}>+ 증가</button>
<button onClick={() => dispatch(decrement())}>- 감소</button>
<button onClick={() => dispatch(reset())}>리셋</button>
</div>
);
}
export default App;
위에서 만든 reducer를 useDispatch를 통해서 불러오고 거기서 increment, decrement, reset함수를 각각 불러오는 식으로 구현이 되었다. dispatch를 불러오는 부분은 tsx 형태로 된 컴포넌트나 페이지 자체가 될 수 있다.
내가 본 코드에서는 테이블 컴포넌트안에서 useDispatch를 활용하였다. 여기서 테이블 컴포넌트는 서비스 전반적으로 사용되는 공통 테이블을 만드는 모듈을 가지고 있었다.
4️⃣ 루트 설정 (index.js)
// src/index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import { Provider } from 'react-redux';
import { store } from './app/store';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<Provider store={store}>
<App />
</Provider>
);
해당 부분에서는 redux Provider를 루트에서 주입해야 redux사용이 가능하다는 점 정도만 이해해도 될것 같다.
내가 보는 프로젝트의 경우 next.js 프레임워크를 사용중이였기 때문에 src의 layout쪽에 redux가 있었기 때문에 해당 부분에서 찾아볼 수 있었다.
요약
Redux 상태 읽기 | useSelector | const count = useSelector(state => state.counter.value) |
액션 실행 | useDispatch | dispatch(increment()), dispatch(reset()) |
정리하자면 위와 같이 useSelector는 상태를 읽어로 때 useDispatch는 액션을 실행할때 사용한 것을 볼 수 있다.
'개발 > frontend' 카테고리의 다른 글
Redux) redux-tool kit createEntityAdapter 설명 (1) | 2025.07.10 |
---|---|
Redux 사용하기 (Redux tool kit) (3) | 2025.07.10 |
Next.js) 프론트엔드에서의 JWT 관리 (1) | 2025.04.25 |
React + Next.js 에서 블록체인 지갑 기반 로그인 시스템 만들기 (프론트엔드) (0) | 2025.04.03 |
Next.js "Use client" 사용법 (1) | 2025.04.02 |