• ABOUT
  • POSTS
  • GUESTBOOK

ยฉ 2025 BlueCool12 All rights reserved.

2025.07.28React

๐Ÿ—ƒ๏ธ Redux ์ œ๋Œ€๋กœ ์ดํ•ดํ•˜๊ธฐ - Store, Action, Reducer, Dispatch

๋ฆฌ์•กํŠธ์—์„œ ์ƒํƒœ ๊ด€๋ฆฌ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ props๋ฅผ ํ†ตํ•ด ์ด๋ฃจ์–ด์ง„๋‹ค. ํ•˜์ง€๋งŒ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์ปค์ง€๊ณ  ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋งŽ์•„์งˆ์ˆ˜๋ก ์ƒํƒœ๋ฅผ ์—ฌ๋Ÿฌ ์ปดํฌ๋„ŒํŠธ์—์„œ ๊ณต์œ ํ•˜๊ฑฐ๋‚˜ ๊นŠ๊ฒŒ ์ „๋‹ฌํ•ด์•ผ ํ•˜๋Š” ์ƒํ™ฉ์ด ๋ฐœ์ƒํ•˜๋ฉด์„œ ์ฝ”๋“œ๊ฐ€ ๋ณต์žกํ•ด์งˆ ์ˆ˜ ์žˆ๋‹ค. 

์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ณ  ์ƒํƒœ ๊ด€๋ฆฌ๋ฅผ ๋ณด๋‹ค ์ฒด๊ณ„์ ์ด๊ณ  ์˜ˆ์ธก ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด ๋“ฑ์žฅํ•œ ๊ฒƒ์ด Redux์ด๋‹ค. ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๋ชจ๋“  ์ƒํƒœ๋ฅผ ํ•˜๋‚˜์˜ ์ค‘์•™ ์ €์žฅ์†Œ(store)์— ๋ณด๊ด€ํ•˜๊ณ  ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•  ๋•Œ์—๋Š” ๋ฐ˜๋“œ์‹œ ์•ก์…˜(action)๊ณผ ๋ฆฌ๋“€์„œ(reducer)๋ฅผ ํ†ตํ•ด ๋ณ€๊ฒฝํ•œ๋‹ค. 

์ด๋Ÿฌํ•œ ๊ตฌ์กฐ ๋•๋ถ„์— ์ƒํƒœ ๋ณ€ํ™”์˜ ํ๋ฆ„์ด ๋ช…ํ™•ํ•˜๊ณ  ๋””๋ฒ„๊น…์ด ์‰ฌ์›Œ์ง€๋ฉฐ ๊ทœ๋ชจ๊ฐ€ ํฐ ํ”„๋กœ์ ํŠธ์—์„œ๋„ ์ผ๊ด€๋œ ๋ฐฉ์‹์œผ๋กœ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค. 
 

# Redux์˜ ํ•ต์‹ฌ ๊ตฌ์„ฑ์š”์†Œ 


Redux๋Š” 3๊ฐ€์ง€ ํ•ต์‹ฌ ๊ตฌ์„ฑ์š”์†Œ๋กœ ๋™์ž‘ํ•œ๋‹ค. 

  • Store
  • Action 
  • Reducer 

    ๊ทธ๋ฆฌ๊ณ  ์ด ๊ตฌ์„ฑ์š”์†Œ๋“ค์„ ์—ฐ๊ฒฐํ•ด ์ฃผ๋Š” ์—ญํ• ์„ ํ•˜๋Š” ๊ฒƒ์ด ๋ฐ”๋กœ Dispatch์ด๋‹ค. 
     



1. Store

Store๋Š” ์•ฑ์˜ ์ „์ฒด ์ƒํƒœ(state)๋ฅผ ๋ณด๊ด€ํ•˜๋Š” ๊ฐ์ฒด๋กœ์จ ํ•˜๋‚˜์˜ ์•ฑ์— ํ•˜๋‚˜์˜ store๊ฐ€ ์กด์žฌํ•˜๊ณ  ์ด store๋Š” ๋ชจ๋“  ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๊ณต์œ ํ•œ๋‹ค. 

createStore()๋กœ ์ƒ์„ฑํ•œ๋‹ค. 

typescript
import { createStore, combineReducers } from "redux";
import { counterReducer } from './counterReducer';

const rootReducer = combineReducers({
  counter: counterReducer
});

export const store = createStore(rootReducer);


์ดํ›„ Provider๋กœ App ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ฐ์‹ธ์ค€๋‹ค. 

typescript

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <Provider store={store}>
    <Counter />
  </Provider>
);


Provider๋Š” ๋ฆฌ์•กํŠธ ์ปดํฌ๋„ŒํŠธ ํŠธ๋ฆฌ ์ „์ฒด์— Redux์˜ store๋ฅผ ์ „๋‹ฌํ•˜๋Š” ์—ญํ• ์„ ํ•˜๋ฉฐ ๋‚ด๋ถ€์˜ ๋ชจ๋“  ์ปดํฌ๋„ŒํŠธ๋“ค์ด Redux ์ƒํƒœ์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋งŒ๋“ค์–ด์ค€๋‹ค. 
 

2. Action

Action์€ ์ƒํƒœ ๋ณ€๊ฒฝ์ด ํ•„์š”ํ•˜๋‹ค๋Š” ์š”์ฒญ์„ ์ „๋‹ฌํ•˜๋Š” ๊ฐ์ฒด์ด๋‹ค. ํ•ญ์ƒ type์ด๋ผ๋Š” ํ•„์ˆ˜ ์†์„ฑ์„ ๊ฐ€์ง€๋ฉฐ ์ƒํ™ฉ์— ๋”ฐ๋ผ payload ๊ฐ™์€ ์ถ”๊ฐ€ ๋ฐ์ดํ„ฐ๋„ ํฌํ•จํ•  ์ˆ˜ ์žˆ๋‹ค.

typescript
const incrementAction = {
  type: 'INCREMENT',
  payload: 1
};


 

3. Reducer

Reducer๋Š” ํ˜„์žฌ ์ƒํƒœ์™€ ์•ก์…˜์„ ๋ฐ›์•„์„œ ์ƒˆ๋กœ์šด ์ƒํƒœ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜์ด๋‹ค. ์ƒํƒœ๋ฅผ ์ง์ ‘ ์ˆ˜์ •ํ•˜์ง€ ์•Š๊ณ  ํ•ญ์ƒ ์ƒˆ๋กœ์šด ์ƒํƒœ ๋ฐ˜ํ™˜ํ•จ์œผ๋กœ์จ ์ƒํƒœ ๋ณ€๊ฒฝ์„ ๊ด€๋ฆฌํ•œ๋‹ค. 

typescript
const counterReducer = (state = { value: 0 }, action) => {
  switch (action.type) {
    case 'INCREMENT':
      return { value: state.value + action.payload };
    default:
      return state;
  }
};


 

4. Dispatch

Dispatch๋Š” ์•ก์…˜์„ ๋ฆฌ๋“€์„œ์— ์ „๋‹ฌํ•ด์„œ ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•˜๋„๋ก ํ•˜๋Š” ํ•จ์ˆ˜์ด๋‹ค. ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์—์„œ dispatch()๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ํ•ด๋‹น ์•ก์…˜์ด ์‹คํ–‰๋˜์–ด ๋ฆฌ๋“€์„œ๋กœ ์ „๋‹ฌ๋˜๊ณ  ๊ทธ์— ๋”ฐ๋ผ ์ƒํƒœ๊ฐ€ ์—…๋ฐ์ดํŠธ๋œ๋‹ค. 

typescript
import { useDispatch, useSelector } from "react-redux";

const Counter = () => {
  const dispatch = useDispatch();
  const count = useSelector((state) => state.counter.value);
  
  const incrementAction = {
    type: 'INCREMENT',
    payload: 1
  };
  
  const handleClick = () => {
    dispatch(incrementAction);
  };
  
  return (
    <div>
      <p>์นด์šดํŠธ: {count}</p>
      <button onClick={handleClick}>+1 ์ฆ๊ฐ€</button>
    </div>
  );
};

export default Counter;

 

์ด์ „ ๊ธ€
๐Ÿ“ ์›น์‚ฌ์ดํŠธ ์„ฑ๋Šฅ ์ธก์ • ๋„๊ตฌ Lighthouse
๋‹ค์Œ ๊ธ€
๐Ÿ“„ Pageable๋กœ ํŽ˜์ด์ง• ์ฒ˜๋ฆฌ ์‰ฝ๊ฒŒ ๊ตฌํ˜„ํ•˜๊ธฐ (+Spring Data JPA)
์žฅ์‹์šฉ ๋กœ๊ณ