Redux

1. ์ƒํƒœ ๊ด€๋ฆฌ

์ „์—ญ ์ƒํƒœ ๊ด€๋ฆฌ

  • ํ”„๋ก ํŠธ์—”๋“œ ๊ฐœ๋ฐœ์—์„œ์˜ ์ƒํƒœ: ๋™์ ์œผ๋กœ ํ‘œํ˜„๋˜๋Š” ๋ฐ์ดํ„ฐ

์ „์—ญ ์ƒํƒœ

  • ์„œ๋กœ ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์‚ฌ์šฉํ•˜๋Š” ์ƒํƒœ์˜ ์ข…๋ฅ˜๊ฐ€ ๋‹ค๋ฅด๋‹ค๋ฉด, ์„œ๋กœ ๋‹ค๋ฅธ ์ถœ์ฒ˜๊ฐ€ ์žˆ์–ด๋„ ๊ดœ์ฐฎ์Œ

  • ํ•˜์ง€๋งŒ ์„œ๋กœ ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋™์ผํ•œ ์ƒํƒœ๋ฅผ ๋‹ค๋ฃฌ๋‹ค๋ฉด, ์„œ๋กœ ๋‹ค๋ฅธ ์ถœ์ฒ˜๋กœ ๊ฐ€์ ธ์˜ค๋Š” ๊ฒƒ์€ ํ”ผํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Œ

๋ฐ์ดํ„ฐ ๋ฌด๊ฒฐ์„ฑ

  • ๋™์ผํ•œ ๋ฐ์ดํ„ฐ๋Š” ํ•ญ์ƒ ๊ฐ™์€ ๊ณณ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค. โ†’ Single source of truth

์ƒํƒœ ๊ด€๋ฆฌ ํˆด์ด ํ•ด๊ฒฐํ•ด์ฃผ๋Š” ๋ฌธ์ œ๋“ค

  • ์ „์—ญ ์ƒํƒœ ์ €์žฅ์†Œ ์ œ๊ณต

  • Props Drilling ์ด์Šˆ ํ•ด๊ฒฐ

Props Drilling

  • ์ƒ์œ„ ์ปดํฌ๋„ŒํŠธ์˜ state๋ฅผ props๋ฅผ ํ†ตํ•ด ์ „๋‹ฌํ•˜๊ณ ์ž ํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ๋กœ ์ „๋‹ฌํ•˜๊ธฐ ์œ„ํ•ด

  • ๊ทธ ์‚ฌ์ด๋Š” props๋ฅผ ์ „๋‹ฌํ•˜๋Š” ์šฉ๋„๋กœ๋งŒ ์“ฐ์ด๋Š” ์ปดํฌ๋„ŒํŠธ๋“ค์„ ๊ฑฐ์น˜๋ฉด์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•˜๋Š” ํ˜„์ƒ

Props Drilling์˜ ๋ฌธ์ œ

  • ์ฝ”๋“œ ๊ฐ€๋…์„ฑ์ด ๋‚˜๋น ์ง

  • ์ฝ”๋“œ์˜ ์œ ์ง€๋ณด์ˆ˜ ๋˜ํ•œ ํž˜๋“ค์–ด์ง

  • state ๋ณ€๊ฒฝ ์‹œ, Props์˜ ์ „๋‹ฌ ๊ณผ์ •์—์„œ ๋ถˆํ•„์š”ํ•˜๊ฒŒ ๊ด€์—ฌ๋œ ์ปดํฌ๋„ŒํŠธ๋“ค ๋˜ํ•œ ๋ฆฌ๋ Œ๋”๋ง ๋ฐœ์ƒํ•ด ์„ฑ๋Šฅ์— ์•…์˜ํ–ฅ

์ด์— ๋Œ€ํ•œ ํ•ด๊ฒฐ์ฑ…

  • ์ปดํฌ๋„ŒํŠธ์™€ ๊ด€๋ จ์žˆ๋Š” state๋Š” ๊ฐ€๋Šฅํ•˜๋ฉด ๊ฐ€๊นŒ์ด ์œ ์ง€ํ•˜๊ธฐ

  • ์ƒํƒœ๊ด€๋ฆฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์‚ฌ์šฉ: ์ „์—ญ์œผ๋กœ ๊ด€๋ฆฌํ•˜๋Š” ์ €์žฅ์†Œ์—์„œ ์ง์ ‘ state ๊บผ๋‚ด ์“ธ ์ˆ˜ ์žˆ๊ธฐ์— Props Drilling ๋ฐฉ์ง€ ํšจ๊ณผ์ 

2. Redux๋ž€

์ปดํฌ๋„ŒํŠธ์™€ ์ƒํƒœ๋ฅผ ๋ถ„๋ฆฌํ•˜์—ฌ ์ „์—ญ์—์„œ ์ƒํƒœ ๊ด€๋ฆฌ๋ฅผ ํ•ด์ค„ ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ์ƒํƒœ ๊ด€๋ฆฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

Redux๊ฐ€ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ์ˆœ์„œ

  1. ์ƒํƒœ๊ฐ€ ๋ณ€๊ฒฝ๋˜์–ด์•ผ ํ•˜๋Š” ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด, ๋ณ€๊ฒฝ๋  ์ƒํƒœ์— ๋Œ€ํ•œ ์ •๋ณด๊ฐ€ ๋‹ด๊ธด Action ๊ฐ์ฒด๊ฐ€ ์ƒ์„ฑ

  2. ์ด Action ๊ฐ์ฒด๋Š” Dispatch ํ•จ์ˆ˜์˜ ์ธ์ž๋กœ ์ „๋‹ฌ๋จ

  3. Dispatch ํ•จ์ˆ˜๋Š” Action ๊ฐ์ฒด๋ฅผ Reducer ํ•จ์ˆ˜๋กœ ์ „๋‹ฌํ•จ

  4. Reducer ํ•จ์ˆ˜๋Š” Action ๊ฐ์ฒด์˜ ๊ฐ’์„ ํ™•์ธํ•˜๊ณ , ๊ทธ ๊ฐ’์— ๋”ฐ๋ผ ์ „์—ญ ์ƒํƒœ ์ €์žฅ์†Œ Store์˜ ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•จ

  5. ์ƒํƒœ๊ฐ€ ๋ณ€๊ฒฝ๋˜๋ฉด, React๋Š” ํ™”๋ฉด์„ ๋‹ค์‹œ ๋ Œ๋”๋ง

  6. ์ฆ‰, Redux์—์„œ๋Š” Action โ†’ Dispatch โ†’ Reducer โ†’ Store ์ˆœ์„œ๋กœ ๋ฐ์ดํ„ฐ๊ฐ€ ๋‹จ๋ฐฉํ–ฅ์œผ๋กœ ํ๋ฆ„

3. Redux ๊ตฌ์กฐ

Store

์ƒํƒœ๊ฐ€ ๊ด€๋ฆฌ๋˜๋Š” ์˜ค์ง ํ•˜๋‚˜๋ฟ์ธ ์ €์žฅ์†Œ ์—ญํ• ๋กœ, Redux ์•ฑ์˜ state๊ฐ€ ์ €์žฅ๋˜์–ด ์žˆ๋Š” ๊ณต๊ฐ„

// `createStore` ๋ฉ”์†Œ๋“œ๋กœ Reducer ์—ฐ๊ฒฐํ•ด store ์ƒ์„ฑ
import { createStore } from 'redux';
const store = createStore(rootReducer);

Reducer

Dispatch์—๊ฒŒ์„œ ์ „๋‹ฌ๋ฐ›์€ Action ๊ฐ์ฒด์˜ type ๊ฐ’์— ๋”ฐ๋ผ์„œ ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝ์‹œํ‚ค๋Š” ํ•จ์ˆ˜

const count = 1

// Reducer ์ƒ์„ฑ์‹œ ์ดˆ๊ธฐ ์ƒํƒœ์˜ ์ธ์ž๋กœ ์š”๊ตฌ
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;
 }
}
// Reducer๊ฐ€ ๋ฆฌํ„ดํ•˜๋Š” ๊ฐ’์ด ์ƒˆ๋กœ์šด ์ƒํƒœ๊ฐ€ ๋จ
// ์ด๋•Œ Reducer๋Š” ์ˆœ์ˆ˜ํ•จ์ˆ˜์—ฌ์•ผ ํ•จ.

Action

Action์€ ์–ด๋–ค ์•ก์…˜์„ ์ทจํ•  ๊ฒƒ์ธ์ง€ ์ •์˜ํ•ด ๋†“์€ ๊ฐ์ฒด๋กœ, type์€ ํ•„์ˆ˜๋กœ ์ง€์ •ํ•ด ์ฃผ์–ด์•ผ ํ•˜๋ฉฐ, ๋Œ€๋ฌธ์ž์™€ Snake Case๋กœ ์ž‘์„ฑํ•จ. ๋ณดํ†ต Action ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค์–ด ์‚ฌ์šฉํ•˜๋Š”๋ฐ, ์ด๋ฅผ ์•ก์…˜ ์ƒ์„ฑ์ž (Action Creator)๋ผ๊ณ  ํ•จ.

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

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

Dispatch

Reducer๋กœ Action์„ ์ „๋‹ฌํ•ด ์ฃผ๋Š” ํ•จ์ˆ˜

// Action ๊ฐ์ฒด๋ฅผ ์ง์ ‘ ์ž‘์„ฑํ•˜๋Š” ๊ฒฝ์šฐ
dispatch( {type: 'INCREASE'} );
dispatch( {type: 'SET_NUMBER', payload: 5} );

// Action Creator๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ
dispatch( increase() );
dispatch( setNumber(5) );

4. Redux Hooks

useDispatch()

Action ๊ฐ์ฒด๋ฅผ Reducer๋กœ ์ „๋‹ฌํ•ด ์ฃผ๋Š” Dispatch ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฉ”์†Œ๋“œ

import {useDispatch} from 'react-redux'

const dispatch = useDispatch()
dispatch(increase())
console.log(counter) // 2

dispatch(setNumber(5))
console.log(counter) // 5

useSelector()

์ปดํฌ๋„ŒํŠธ์™€ state๋ฅผ ์—ฐ๊ฒฐํ•ด Redux์˜ state์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ๋ฉ”์†Œ๋“œ

// Redux Hooks ๋ฉ”์†Œ๋“œ๋Š” redux๊ฐ€ ์•„๋‹Œ react-redux์—์„œ ๋ถˆ๋Ÿฌ์˜ด
import {useSelector} from 'react-redux'
const counter = useSelector(state => state)
console.log(counter) // 1

5. Redux์˜ ์„ธ ๊ฐ€์ง€ ์›์น™

Single source of truth

  • ๋™์ผํ•œ ๋ฐ์ดํ„ฐ๋Š” ํ•ญ์ƒ ๊ฐ™์€ ๊ณณ์—์„œ ๊ฐ€์ง€๊ณ  ์™€์•ผ ํ•จ

  • Redux์—๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๋Š” Store ๋ผ๋Š” ํ•˜๋‚˜๋ฟ์ธ ๊ณต๊ฐ„์ด ์žˆ์Œ

State is read-only

  • ์ƒํƒœ๋Š” ์ฝ๊ธฐ ์ „์šฉ

  • React์—์„œ ์ƒํƒœ๊ฐฑ์‹ ํ•จ์ˆ˜๋กœ๋งŒ ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ–ˆ๋˜ ๊ฒƒ์ฒ˜๋Ÿผ Redux์˜ ์ƒํƒœ๋„ ์ง์ ‘ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†์Œ์„ ์˜๋ฏธ

  • ์ฆ‰, Action ๊ฐ์ฒด๊ฐ€ ์žˆ์–ด์•ผ๋งŒ ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅ

Changes are made with pure functions

  • ๋ณ€๊ฒฝ์€ ์ˆœ์ˆ˜ํ•จ์ˆ˜๋กœ๋งŒ ๊ฐ€๋Šฅ

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

Last updated