[๐Ÿ’ป ์ฝ”๋“œ์Šคํ…Œ์ด์ธ  FE 44๊ธฐ]Redux

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

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

Redux์˜ ํ๋ฆ„์„ ๋ฐฐ์šฐ๋ฉด์„œ ํŽ˜์–ด๋ถ„๊ณผ ํ•จ๊ป˜ ๊ณผ์ œ๋ฅผ ์ง„ํ–‰ํ–ˆ๋‹ค.


๐Ÿ“ ๋ฐฐ์šด ๊ฒƒ

โœ”๏ธ Redux

  • ์ƒํƒœ ๊ด€๋ฆฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ
  • ์ „์—ญ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ์ €์žฅ์†Œ Store๋ฅผ ์ œ๊ณตํ•ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•œ๋‹ค.
  • React ๋ง๊ณ ๋„ JavaScript ๋“ฑ ์–ด๋Š ๋ฌธ๋ฒ•์—์„œ๋„ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋‹ค.

โœ”๏ธ Redux ๊ตฌ์กฐ

Action(๊ฐ์ฒด) โ†’ Dispatch(ํ•จ์ˆ˜) โ†’ Reducer(ํ•จ์ˆ˜) โ†’ Store(์ €์žฅ์†Œ)
๋ฐ์ดํ„ฐ๊ฐ€ ๋‹จ๋ฐฉํ–ฅ์œผ๋กœ ํ๋ฅธ๋‹ค.

1. ์ƒํƒœ๊ฐ€ ๋ณ€๊ฒฝ๋˜์–ด์•ผ ํ•˜๋Š” ์ด๋ฒคํŠธ ๋ฐœ์ƒ ์‹œ ๋ณ€๊ฒฝ๋  ์ƒํƒœ์— ๋Œ€ํ•œ ์ •๋ณด๊ฐ€ ๋‹ด๊ธด Action ๊ฐ์ฒด๊ฐ€ ์ƒ์„ฑ
2. Action ๊ฐ์ฒด => Dispatch ํ•จ์ˆ˜ ์ธ์ž๋กœ ์ „๋‹ฌ
3. Dispatch ํ•จ์ˆ˜ => Action ๊ฐ์ฒด๋ฅผ Reducer ํ•จ์ˆ˜๋กœ ์ „๋‹ฌ
4. Reducer ํ•จ์ˆ˜ => Action ๊ฐ์ฒด์˜ ๊ฐ’์„ ํ™•์ธํ•˜๊ณ , ๊ทธ ๊ฐ’์— ๋”ฐ๋ผ ์ „์—ญ ์ƒํƒœ ์ €์žฅ์†Œ Store์˜ ์ƒํƒœ ๋ณ€๊ฒฝ
5. ์ƒํƒœ๊ฐ€ ๋ณ€๊ฒฝ๋˜๋ฉด, React๋Š” ํ™”๋ฉด์„ ๋‹ค์‹œ ๋ Œ๋”๋ง

๐Ÿ’ป Store

  • ์ƒํƒœ๊ฐ€ ๊ด€๋ฆฌ๋˜๋Š” ์˜ค์ง ํ•˜๋‚˜ ๋ฟ์ธ ์ €์žฅ์†Œ์˜ ์—ญํ• 
  • Redux ์•ฑ์˜ state๊ฐ€ ์ €์žฅ๋˜์–ด ์žˆ๋Š” ๊ณต๊ฐ„
  • createStore ๋ฉ”์„œ๋“œ๋ฅผ ์ด์šฉํ•ด Reducer ์—ฐ๊ฒฐ ํ›„ Store ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.
//createStore ๋ถˆ๋Ÿฌ์˜ค๊ธฐ
import {createStore} from 'redux'; 
// createStore๋ฉ”์„œ๋“œ ์ด์šฉํ•ด store ์ƒ์„ฑ
// ์ธ์ž๋Š” reducer ํ•จ์ˆ˜๋ฅผ ๋„ฃ์–ด์ค€๋‹ค.
const store = createStore(rootReducer)

๐Ÿ’ป Reducer

  • Dispatch์—๊ฒŒ์„œ ์ „๋‹ฌ ๋ฐ›์€ Action ๊ฐ์ฒด์˜ type๊ฐ’์— ๋”ฐ๋ผ ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝ์‹œํ‚ค๋Š” ํ•จ์ˆ˜
  • Reducer๋Š” ์ˆœ์ˆ˜ํ•จ์ˆ˜์—ฌ์•ผ ํ•œ๋‹ค. (์™ธ๋ถ€ ์š”์ธ์œผ๋กœ ์ธํ•ด ๊ธฐ๋Œ€ํ•œ ๊ฐ’์ด ์•„๋‹Œ ์—‰๋šฑํ•œ ๊ฐ’์œผ๋กœ ์ƒํƒœ๊ฐ€ ๋ณ€๊ฒฝ๋˜๋Š” ์ผ์ด ์—†์–ด์•ผํ•˜๊ธฐ ๋•Œ๋ฌธ)
    - ์ฒซ๋ฒˆ์งธ ์ธ์ž : ๊ธฐ์กด state๊ฐ€ ๋“ค์–ด์˜จ๋‹ค.
    (default value๋ฅผ ๊ผญ ์„ค์ •ํ•ด ์ฃผ์–ด์•ผํ•œ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š์„ ๊ฒฝ์šฐ undefined๊ฐ€ ํ• ๋‹น ๋˜๊ธฐ ๋•Œ๋ฌธ)
    - ๋‘๋ฒˆ์งธ ์ธ์ž : action ๊ฐ์ฒด
  • action ๊ฐ์ฒด์—์„œ ์ •์˜ํ•œ type์— ๋”ฐ๋ผ ์ƒˆ๋กœ์šด state๋ฅผ ๋ฆฌํ„ด
  • ์ƒˆ๋กœ์šด state๋Š” ์ „์—ญ ๋ณ€์ˆ˜ ์ €์žฅ์†Œ Store์— ์ €์žฅ๋œ๋‹ค.
// ๊ธฐ๋ณธ ๋ฌธ๋ฒ•
const reducer = () => {}
// store ์ธ์ž๋Š” reducer 
const store = createStore(reducer)
.
.
.
const count = 1

// Reducer๋ฅผ ์ƒ์„ฑํ•  ๋•Œ์—๋Š” ์ดˆ๊ธฐ ์ƒํƒœ๋ฅผ ์ธ์ž๋กœ ์š”๊ตฌํ•œ๋‹ค.
// state = count = 1
const counterReducer = (state = count, action) => {

  // Action ๊ฐ์ฒด์˜ type ๊ฐ’์— ๋”ฐ๋ผ ๋ถ„๊ธฐํ•˜๋Š” switch ์กฐ๊ฑด๋ฌธ
  switch (action.type) {

    //action === 'INCREASE'์ผ ๊ฒฝ์šฐ
    case 'INCREASE':
			return state + 1

    // action === 'DECREASE'์ผ ๊ฒฝ์šฐ
    case 'DECREASE':
			return state - 1

    // action === 'SET_NUMBER'์ผ ๊ฒฝ์šฐ
    case 'SET_NUMBER':
			return action.payload

    // ํ•ด๋‹น ๋˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์—†์„ ๋• ๊ธฐ์กด ์ƒํƒœ๋ฅผ ๊ทธ๋Œ€๋กœ ๋ฆฌํ„ด
    default:
      return state;
	}
}

// store ์ธ์ž๋Š” reducer 
const store = createStore(counterReducer)
  • Reducer๋ฅผ ์ƒ์„ฑํ•  ๋•Œ์—๋Š” ์ดˆ๊ธฐ ์ƒํƒœ๋ฅผ ์ธ์ž๋กœ ์š”๊ตฌํ•œ๋‹ค.
  • Action ๊ฐ์ฒด์˜ type ๊ฐ’์— ๋”ฐ๋ผ ๋ถ„๊ธฐํ•˜๋Š” switch ์กฐ๊ฑด๋ฌธ์„ ์‚ฌ์šฉํ•œ๋‹ค. (if๋ฌธ ์‚ฌ์šฉํ•ด๋„ ๊ฐ€๋Šฅ ํ•œ ๋“ฏ)
  • Reducer๊ฐ€ ๋ฆฌํ„ดํ•˜๋Š” ๊ฐ’์ด ์ƒˆ๋กœ์šด ์ƒํƒœ๊ฐ€ ๋œ๋‹ค.

โ—๏ธ์—ฌ๋Ÿฌ ๊ฐœ์˜ Reducer๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ

combineReducers๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด ํ•˜๋‚˜์˜ Reducer๋กœ ํ•ฉ์ณ์ค„ ์ˆ˜ ์žˆ๋‹ค.

// combineReducers ๋ถˆ๋Ÿฌ์˜ค๊ธฐ
import { combineReducers } from 'redux';
// combineReducers ์‚ฌ์šฉํ•˜๊ธฐ
const rootReducer = combineReducers({
  	//Reducer ํ•จ์ˆ˜ ์ถ”๊ฐ€ํ•ด ์ฃผ๊ธฐ
	counterReducer,
  	anyReducer,
  	...
})

๐Ÿ’ป Action

  • ์–ด๋–ค ์•ก์…˜์„ ์ทจํ•  ๊ฒƒ์ธ์ง€ ์ •์˜ํ•ด ๋†“์€ ๊ฐ์ฒด์ด๋‹ค. (์–ด๋–ป๊ฒŒ state๋ฅผ ๋ณ€๊ฒฝํ• ์ง€ ์ •์˜ํ•ด ๋‘” ๊ฐ์ฒด)
  • type์€ ํ•„์ˆ˜๋กœ ์ง€์ •ํ•ด ์ฃผ์–ด์•ผ ํ•œ๋‹ค.
    - Action ๊ฐ์ฒด๊ฐ€ ์–ด๋–ค ๋™์ž‘์„ ํ•˜๋Š”์ง€ ๋ช…์‹œํ•ด ์ฃผ๋Š” ์—ญํ• 
    - ์ง€์ •ํ•œ type์— ๋”ฐ๋ผ Reducer ํ•จ์ˆ˜์—์„œ ์ƒˆ๋กœ์šด state๋ฅผ ๋ฆฌํ„ดํ•˜๊ฒŒ ๋œ๋‹ค.
  • ๋Œ€๋ฌธ์ž, Snake Case๋กœ ์ž‘์„ฑ
  • Action ๊ฐ์ฒด๋Š” Dispatch ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด Reducer ํ•จ์ˆ˜ ๋‘๋ฒˆ์งธ ์ธ์ž๋กœ ์ „๋‹ฌ๋œ๋‹ค.
  • ํ•„์š”์— ๋”ฐ๋ผ payload๋ฅผ ์ž‘์„ฑํ•ด ๊ตฌ์ฒด์ ์ธ ๊ฐ’์„ ์ „๋‹ฌํ•œ๋‹ค.
//payload๊ฐ€ ํ•„์š” ์—†๋Š” ๊ฒฝ์šฐ
{ type: 'INCREASE' }

// payload๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ
{ type: 'SET_NUMBER', payload: 5 }

โ—๏ธ ์•ก์…˜ ์ƒ์„ฑ์ž(Action Creator) : Action์€ ์ง์ ‘ ์ž‘์„ฑํ•˜๊ธฐ ๋ณด๋‹จ Action ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค์–ด ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ๋‹ค.

// payload๊ฐ€ ํ•„์š” ์—†๋Š” ๊ฒฝ์šฐ
const increase = () => {
  return {
    type: 'INCREASE'
  }
}
// payload๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ
const setNumber = (num) => {
  return {
    type: 'SET_NUMBER',
    payload: num
  }
}

๐Ÿ’ป Dispatch

  • Reducer๋กœ Action์„ ์ „๋‹ฌํ•ด ์ฃผ๋Š” ํ•จ์ˆ˜
  • Dispatch์˜ ์ „๋‹ฌ์ธ์ž๋กœ Action ๊ฐ์ฒด๊ฐ€ ์ „๋‹ฌ๋œ๋‹ค.
  • Action ๊ฐ์ฒด๋ฅผ ์ „๋‹ฌ ๋ฐ›์€ Dispatchํ•จ์ˆ˜๋Š” Reducer๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.
// Action ๊ฐ์ฒด๋ฅผ ์ง์ ‘ ์ž‘์„ฑํ•˜๋Š” ๊ฒฝ์šฐ
dispatch( { type: 'INCREASE' } );
dispatch( { type: 'SET_NUMBER', payload: 5 } );

// ์•ก์…˜ ์ƒ์„ฑ์ž(Action Creator)๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ
// export๋ฅผ ๋ถ™์—ฌ์ฃผ๋ฉด ๋‹ค๋ฅธ ํŒŒ์ผ์—์„œ ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.
export const increase = () => {
  return {
    type: 'INCREASE'
  }
}
export const setNumber = (num) => {
  return {
    type: 'SET_NUMBER',
    payload: num
  }
}
dispatch( increase() );
dispatch( setNumber(5) );

๐Ÿ“ Redux Hook

  • React-Redux์—์„œ Redux๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋Š” Hook ๋ฉ”์„œ๋“œ๋ฅผ ์ œ๊ณต
  • useDispatch(), useSelector() ๋ฉ”์„œ๋“œ๋ฅผ ๊ธฐ์–ตํ•˜๋ฉด ์ข‹๋‹ค.

๐Ÿ’ป useDispatch()

  • Action ๊ฐ์ฒด๋ฅผ Reducer๋กœ ์ „๋‹ฌํ•ด ์ฃผ๋Š” Dispatch ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฉ”์„œ๋“œ
  • dispatch ํ•จ์ˆ˜๋Š” ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ์•ˆ์—์„œ ์‚ฌ์šฉ๋œ๋‹ค.
// Redux Hooks ๋ฉ”์„œ๋“œ๋Š” 'redux'๊ฐ€ ์•„๋‹ˆ๋ผ 'react-redux'์—์„œ ๋ถˆ๋Ÿฌ์˜จ๋‹ค.
// useDispatch ๋ถˆ๋Ÿฌ์˜ค๊ธฐ
import { useDispatch } from 'react-redux';
// ์™ธ๋ถ€ ํŒŒ์ผ์—์„œ ์ž‘์—… ํ•œ increase,decrease ๋ถˆ๋Ÿฌ์˜ค๊ธฐ
import { increase,decrease } from './index.js';

const dispatch = useDispatch()
dispatch( increase() )
dispatch( setNumber(5) )

๐Ÿ’ป useSelector()

  • ์ปดํฌ๋„ŒํŠธ์™€ state๋ฅผ ์—ฐ๊ฒฐํ•ด Redux์˜ state์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ๋ฉ”์„œ๋“œ
  • state๊ฐ€ ํ•„์š”ํ•œ ์ปดํฌ๋„ŒํŠธ์—์„œ ์ „์—ญ ๋ณ€์ˆ˜ ์ •์žฅ์†Œ store์— ์ €์žฅ๋œ state๋ฅผ ์‰ฝ๊ฒŒ ๋ถˆ๋Ÿฌ์˜ฌ ์ˆ˜ ์žˆ๋‹ค.
// Redux Hooks ๋ฉ”์„œ๋“œ๋Š” 'redux'๊ฐ€ ์•„๋‹ˆ๋ผ 'react-redux'์—์„œ ๋ถˆ๋Ÿฌ์˜จ๋‹ค.
// useSelector ๋ถˆ๋Ÿฌ์˜ค๊ธฐ
import { useSelector } from 'react-redux

const counter = useSelector(state => state)

๐Ÿ“ Redux์˜ ์„ธ๊ฐ€์ง€ ์›์น™

1. Single source of truth

  • ๋™์ผํ•œ ๋ฐ์ดํ„ฐ๋Š” ํ•ญ์ƒ ๊ฐ™์€ ๊ณณ์—์„œ ๊ฐ€์ง€๊ณ  ์™€์•ผํ•œ๋‹ค.
  • Redux์—๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๋Š” Store (๋‹จ ํ•˜๋‚˜๋ฟ์ด ๊ณต๊ฐ„)

2. State is read-only

  • ์ƒํƒœ๋Š” ์ฝ๊ธฐ ์ „์šฉ
  • Redux์˜ ์ƒํƒœ๋„ ์ง์ ‘ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†๋‹ค.
  • Action ๊ฐ์ฒด๊ฐ€ ์žˆ์–ด์•ผ ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋‹ค.

3. Changes are made with pure functions

  • ๋ณ€๊ฒฝ์€ ์ˆœ์ˆ˜ํ•จ์ˆ˜๋กœ๋งŒ ๊ฐ€๋Šฅํ•˜๋‹ค.
  • ์ƒํƒœ๊ฐ€ ์—‰๋šฑํ•œ ๊ฐ’์œผ๋กœ ๋ณ€๊ฒฝ๋˜๋Š” ์ผ์ด ์—†๋„๋ก ์ˆœ์ˆ˜ํ•จ์ˆ˜๋กœ ์ž‘์„ฑ๋˜์–ด์•ผํ•œ๋‹ค. (Reducer)

โœ๏ธ ๋งˆ์น˜๋ฉฐ

Redux์˜ ํ๋ฆ„์„ ์ดํ•ดํ•˜๋ฉด์„œ ์ด๋ฒˆ ๊ณผ์ œ๋ฅผ ์ง„ํ–‰ํ–ˆ๋‹ค.
์•ฝ๊ฐ„ ์ถ”์ƒ์ ์ธ ๊ฐœ๋…์ด ๋งŽ์•„์„œ ํ—ท๊ฐˆ๋ฆฌ๋Š” ๋ถ€๋ถ„์ด ์žˆ๊ธฐ๋„ ํ–ˆ๋‹ค.

๊ธ€๋กœ ๋ณด๊ณ  ์ดํ•ดํ•˜๊ธฐ ๋ณด๋‹ค๋Š” ๊ณผ์ œ๋ฅผ ํ’€์–ด๋ณด๋ฉด์„œ
์ž‘์„ฑํ•˜๊ณ  ์–ด๋–ป๊ฒŒ ํ๋ฆ„์ด ์ง„ํ–‰๋˜๋Š”์ง€ ํ™•์ธ ํ•˜๋‹ˆ
์ดํ•ดํ•˜๋Š”๋ฐ ๋„์›€์ด ๋œ ๊ฑฐ ๊ฐ™๋‹ค.

์ด๋ฒˆ ํŽ˜์–ด๋ถ„์ด ๋„ˆ๋ฌด ์ž˜ ํ•˜์‹œ๊ธฐ๋„ ํ•˜๊ณ 
์ฝ”๋“œ์Šคํ…Œ์ด์ธ ๊ฐ€ ์˜๋„ํ•œ ๊ณผ์ œ ์ฃผ์ œ๋ฅผ ์ž˜ ํŒŒ์•…ํ•ด ์ฃผ์…”์„œ
๊ณผ์ œ ์ดํ›„ ์ง„ํ–‰๋˜๋Š” ์ž์Šต ์‹œ๊ฐ„์— ํ•™์Šต ๋ฐฉํ–ฅ์„ ์ž˜ ์žก์„ ์ˆ˜ ์žˆ์—ˆ๋˜ ๊ฑฐ ๊ฐ™๋‹ค.

React, Redux์˜ ์ƒํƒœ๋ฅผ ์–ด๋–ป๊ฒŒ ๊ด€๋ฆฌํ•˜๋Š”์ง€
๊ทธ๋ฆผ์„ ๊ทธ๋ฆฌ๋ฉด์„œ ์ง„ํ–‰์„ ํ•ด์•ผ ๋„์›€ ๋œ๋‹ค.

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

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