[๐Ÿ’ป ์ฝ”๋“œ์Šคํ…Œ์ด์ธ  FE 44๊ธฐ] โœจ์•ผ๊ฐ„์ž์œจํ•™์Šต๋ฐ˜โœจ Redux ์‹ค์Šต ์˜์‚ฌ์ฝ”๋“œ ์ž‘์„ฑ

JiEunยท2023๋…„ 4์›” 25์ผ
0
post-thumbnail

โœ”๏ธ ์‹œ์ž‘

์ด๋ฒˆ ์ข…ํ•ฉ ํ€ด์ฆˆ ์ค‘๋ณต ์ •๋‹ต์ด ๋งŽ์•˜๋Š”๋ฐ ๋‘˜ ๋‹ค ์•„๊น๊ฒŒ ํ•˜๋‚˜ ์”ฉ ๋น ์ ธ์„œ
์•ผ๊ฐ„์ž์œจํ•™์Šต๋ฐ˜(๋ฐ˜๋”ง๋ถˆ์ด๋ฐ˜์—์„œ ๋ณ€๊ฒฝ ๋จ)์— ์„ ์ •๋˜์—ˆ๋‹ค.


๐Ÿ“ Redux ์‹ค์Šต

์˜ค๋Š˜ ํ•™์Šตํ•œ ๋‚ด์šฉ

  • ์ „์—ญ ์ƒํƒœ๊ด€๋ฆฌ์˜ ํ•„์š”์„ฑ์„ ์ดํ•ดํ•œ๋‹ค.
  • React์˜ Props Drilling์ด ๋ฌธ์ œ๊ฐ€ ๋˜๋Š” ์ƒํ™ฉ์„ ์ดํ•ดํ•œ๋‹ค.
  • Redux์˜ ๊ตฌ์„ฑ ์š”์†Œ์™€ ๊ธฐ๋ณธ ์‚ฌ์šฉ๋ฒ•์„ ๊ธฐ์–ตํ•œ๋‹ค.

Redux๋Š” Action - Dispatch - Reducer - Store์ˆœ์œผ๋กœ ์ง„ํ–‰๋œ๋‹ค.

  • Action์—์„œ ๊ฐ์ฒด ํ˜•์‹์˜ type์„ ๋งŒ๋“ค์–ด ์–ด๋–ค ์•ก์…˜์„ ์ค„ ๊ฒƒ์ธ์ง€ ๊ฒฐ์ •ํ•œ๋‹ค.
  • Dispatch ์ธ์ž๋Š” Action ๊ฐ์ฒด๋กœ Reducer ํ•จ์ˆ˜์— ์ „๋‹ฌํ•œ๋‹ค.
  • Reducer๋Š” Action ๊ฐ์ฒด์˜ type์— ๋”ฐ๋ผ ๊ฐ’์„ ๋‹ค๋ฅด๊ฒŒ ํ•ด์ฃผ๋ฉฐ Store์˜ state๋ฅผ ๋ณ€๊ฒฝํ•ด ์ค€๋‹ค.

๐Ÿ’ป index.js

  • Action, Reducer, Store ์ž‘์—…์„ ํ•ด์ฃผ์—ˆ๋‹ค.
  • ์ž‘์—…์— ์ง„ํ–‰ํ•˜๊ธฐ ์ „ Provider, createStore๋ฅผ ๋ถˆ๋Ÿฌ์™€์•ผํ•œ๋‹ค.
import React from 'react';
import { createRoot } from 'react-dom/client';
// Provider ๋ถˆ๋Ÿฌ์˜ค๊ธฐ
import { Provider } from 'react-redux';
// createStore ๋ถˆ๋Ÿฌ์˜ค๊ธฐ
import { legacy_createStore as createStore } from 'redux';
import App from './App';

const rootElement = document.getElementById('root');
const root = createRoot(rootElement);

// Action type ๋ณ€์ˆ˜๋กœ ์„ ์–ธํ•˜๊ธฐ
// ์˜คํƒ€ ๋ฐฉ์ง€, ์žฌ์‚ฌ์šฉ์„ฑ, ์ž๋™ ์ž…๋ ฅ์— ์ข‹๋‹ค.
const PLUS = 'PLUS';
const MINUS = 'MINUS';

// Action ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋กœ ๋งŒ๋“ค์–ด ๊ด€๋ฆฌํ•˜๊ธฐ
// ์™ธ๋ถ€์—์„œ ์‚ฌ์šฉ ๊ฐ€๋Šฅ ํ•˜๋„๋ก export ๋ถ™์—ฌ์ฃผ๊ธฐ
export const increase = () => {
  return {
    type: PLUS,
  };
};

export const decrease = () => {
  return {
    type: MINUS,
  };
};

const count = 1;

// reducer ํ•จ์ˆ˜ ์ƒ์„ฑ Action type์— ๋”ฐ๋ฅธ ๋‹ค๋ฅธ ์ด๋ฒคํŠธ ์ฃผ๊ธฐ
// ์ฒซ๋ฒˆ์งธ ์ธ์ž: state, ๋‘๋ฒˆ์งธ ์ธ์ž: action
const reducer = (state = count, action) => {
  switch (action.type) {
    case PLUS:
      return state + 1;
    case MINUS:
      return state - 1;
    default:
      return state;
  }
};

// store ์ƒ์„ฑ ํ›„
// reducer ํ•จ์ˆ˜ ์ธ์ž๋กœ ์ „๋‹ฌ
const store = createStore(reducer);

root.render(
  // Provider ์ปดํฌ๋„ŒํŠธ ์ƒ์„ฑ ํ›„
  // store props๋กœ ์ „๋‹ฌํ•˜๊ธฐ
  <Provider store={store}>
    <App />
  </Provider>
);

๐Ÿ’ป App.js

  • React Hook์„ ํ™œ์šฉํ•ด ์ง„ํ–‰ํ•œ๋‹ค.
    - useSelector๋ฅผ ์ด์šฉํ•ด state์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค.
    - useDispatch๋ฅผ ์ด์šฉํ•ด dispatch ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
import React from 'react';
import './style.css';
// useSelector, useDispatch ๋ถˆ๋Ÿฌ์˜ค๊ธฐ
import { useSelector, useDispatch } from 'react-redux';
// index.js์— ์žˆ๋Š” increase, decrease ๋ถˆ๋Ÿฌ์˜ค๊ธฐ
import { increase, decrease } from './index.js';

export default function App() {
  // useDispatch๋ฅผ ์ด์šฉํ•ด dispatch ํ•จ์ˆ˜ ์‚ฌ์šฉ
  const dispatch = useDispatch();
  // useSelector๋ฅผ ์ด์šฉํ•ด state ์ ‘๊ทผ
  const state = useSelector((state) => state);

  const plusNum = () => {
    // dispatchํ•จ์ˆ˜ ์ธ์ž๋Š” Action type์˜ ๊ฐ’
    dispatch(increase());
  };

  const minusNum = () => {
    // dispatchํ•จ์ˆ˜ ์ธ์ž๋Š” Action type์˜ ๊ฐ’
    dispatch(decrease());
  };

  return (
    // state ๊ฐ’์œผ๋กœ ๋ณ€๊ฒฝ ํ•ด ์ฃผ๊ธฐ ${state}
    <div className="container">
      <h1>{`Count: ${state}`}</h1>
      <div>
        <button className="plusBtn" onClick={plusNum}>
          +
        </button>
        <button className="minusBtn" onClick={minusNum}>
          -
        </button>
      </div>
    </div>
  );
}

์™„์„ฑ

์ž˜ ์ž‘๋™ํ•˜๋Š” ๊ฑธ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

์ž˜ ๋ชจ๋ฅด๋Š” ๋ถ€๋ถ„

  • ์™ธ๋ถ€์— ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ export ๋ถ™์—ฌ ์ฃผ๋Š”๊ฑธ ์•Œ๊ฒŒ ๋˜์—ˆ๋‹ค
export const increase = () => {
  return {
    type: PLUS,
  };
};
  • Action์˜ type์„ ๋ณ€์ˆ˜๋กœ ๊ด€๋ฆฌํ•˜๋ฉด ์˜คํƒ€ ๋ฐฉ์ง€, ์ž๋™์™„์„ฑ, ์žฌ์‚ฌ์šฉ์„ฑ์— ์šฉ์ดํ•˜๋‹ค.
const PLUS = 'PLUS';
const MINUS = 'MINUS';

export const increase = () => {
  return {
    type: PLUS,
  };
};

export const decrease = () => {
  return {
    type: MINUS,
  };
};
  • state์˜ ๊ฐ’์„ ํ›ผ์† ํ•˜๋ฉด ์•ˆ๋œ๋‹ค.(์›๋ณธ ํ›ผ์†x)
    - spread syntax(...state), Object.assign ๋“ฑ์„ ์ด์šฉํ•ด ์ž‘์—…ํ•ด ์ค€๋‹ค.(๊ฐ’ ๋ณต์‚ฌ)
  • Action์ค‘
    - payload๋Š” type์™ธ์— ๊ตฌ์ฒด์ ์œผ๋กœ ๊ฐ’์„ ์„ค์ •ํ•ด ์ฃผ๋Š” ๊ฒƒ์ด๋‹ค.
    - ๊ผญ payload๋ผ๊ณ  ์ด๋ฆ„์„ ์ง€์–ด์ฃผ์ง€ ์•Š์•„๋„ ๋˜๋Š” ๊ฑฐ ๊ฐ™๋‹ค.
    - action ๊ฐ’์„ ๋ถˆ๋Ÿฌ ์˜ฌ ๋•Œ๋Š” ๊ฐ์ฒด ํ˜•์‹ ์ฒ˜๋Ÿผ action.type, action.payload ๋“ฑ์œผ๋กœ ์ž‘์„ฑํ•˜๋ฉด ๋œ๋‹ค.
export const increase = () => {
  return {
    type: PLUS,
    payload: {
    	id
    }
  };
};

์–ด๋ ค์› ๋˜ ๋ถ€๋ถ„

  • useDispatch, useSelector๋ฅผ ์ปดํฌ๋„ŒํŠธ ์ตœ์ƒ์œ„์— ๋„ฃ์–ด์ฃผ๋ฉด ๋˜๋Š”๋ฐ ๊ทธ ๋ฐ–์— ๋„ฃ์–ด์ค˜ ํ•œ์ฐธ ํ—ค๋งธ๋˜ ๊ฑฐ ๊ฐ™๋‹ค.
// ์ดˆ๋ฐ˜์— ์ž‘์„ฑํ•œ ์œ„์น˜
// const dispatch = useDispatch();
// const state = useSelector((state) => state);
export default function App() {
  const dispatch = useDispatch();
  const state = useSelector((state) => state);
  return (
  );
}

โœ๏ธ ๋Š๋‚€์ 

Redux๋Š” ํ๋ฆ„์˜ ์ˆœ์„œ๋งŒ ์ดํ•ดํ•˜๋ฉด ์ž‘์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ์ƒ๊ฐ ๋ณด๋‹ค ๊ฐ„๋‹จํ–ˆ๋˜ ๊ฒƒ ๊ฐ™๋‹ค.

๋‹จ, ๊ทธ ํ๋ฆ„์„ ์ดํ•ดํ•˜๋Š”๋ฐ ์˜ค๋žœ ์‹œ๊ฐ„์ด ๊ฑธ๋ ธ๋‹ค.

profile
๐Ÿ’ป ํ”„๋ก ํŠธ์—”๋“œ๋ฅผ ๋ชฉํ‘œ๋กœ ์„ฑ์žฅ ์ค‘! (์•Œ์•„๋ดค๋˜ ๋‚ด์šฉ ๋“ฑ์„ ์ •๋ฆฌํ•˜๊ธฐ)

0๊ฐœ์˜ ๋Œ“๊ธ€