๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
  • ์žฅ์›์ต ๊ธฐ์ˆ ๋ธ”๋กœ๊ทธ
๐Ÿ“บ Front End/- React, Next.js

[Redux] ๋ฆฌ๋•์Šค๋ฅผ ๊ตฌ์„ฑํ•˜๋Š” 5๊ฐœ์˜ ํ•ต์‹ฌ Action, Reducer, Store, Dispatch, Subscribe

by Wonit 2020. 12. 1.

์˜ค๋Š˜์€ ๋ฆฌ๋•์Šค์˜ ํ•ต์‹ฌ ๋ฉค๋ฒ„์ธ 5ํ˜•์ œ๋ฅผ ์•Œ์•„๋ณด์ž.

  • Action
  • Reducer
  • Store
  • Dispatch
  • Subscribe

์–˜๋“ค์„ ์•Œ์•„๋ณผ ๊ฒƒ์ธ๋ฐ ์ผ๋‹จ ์˜ค๋Š˜ ๊ฐ€์žฅ ์ค‘์š”ํ•œ ๊ฒƒ์€ ํ๋ฆ„์„ ์•Œ์•„์•ผํ•œ๋‹ค.

 

๋‹ค๋ฅธ ์˜ˆ์ œ๋“ค๊ณผ ๋‹ค๋ฅด๊ฒŒ ์ด๋ฒˆ ๊ธ€์— ๋‚˜์˜ค๋Š” ์†Œ์Šค์ฝ”๋“œ๋Š” ๋ณธ์ธ์ด ์ง์ ‘ ํƒ€์ดํ•‘ ํ•˜๋Š” ๊ฒƒ์„ ๊ถŒ์žฅํ•˜์ง€ ์•Š๋Š”๋‹ค.

 

๊ทธ๋ƒฅ ํ๋ฆ„๋งŒ ์ดํ•ดํ•˜๋Š”๋ฐ ์˜จ ํž˜์„ ์Ÿ์„๊ฒƒ์„ ์ถ”์ฒœํ•œ๋‹ค.

Redux

์šฐ๋ฆฌ๋Š” ์ง€๋‚œ ์‹œ๊ฐ„ ์™œ ๋ฆฌ๋•์Šค๋ฅผ ์•Œ์•„์•ผํ•˜๋Š”์ง€์™€ ๋ฆฌ๋•์Šค๋Š” ์–ด๋–ค ํŠน์ง•์„ ๊ฐ–๊ณ  ์žˆ๋Š”์ง€ ์•Œ์•„๋ณด์•˜๋‹ค.

 

์˜ค๋Š˜ ์‹œ๊ฐ„์—๋Š” ๋ฆฌ๋•์Šค๋ฅผ ๊ตฌ์„ฑํ•ด๋Š” ํ•ต์‹ฌ 5ํ˜•์ œ์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณผ ๊ฒƒ์ด๋‹ค.

 

  • Action
  • Reducer
  • Store
  • Dispatch
  • Subscribe

 

์–˜๋“ค์ด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ตฌ์กฐ๋ฅผ ๋„๊ฒŒ ๋œ๋‹ค.

 

์ด ๊ทธ๋ฆผ์„ ์ž˜ ๋ณด๊ณ  ํ•˜๋‚˜ ํ•˜๋‚˜ ๋”ฐ๋ผ๊ฐ€๋ณด์ž.

 

์šฐ์„  ์‹œ์ž‘ํ•˜๊ธฐ ์ „์— ๋ฆฌ๋•์Šค๋ฅผ ํŒจํ‚ค์ง€๋กœ ์„ค์น˜๋ฅผ ํ•ด์•ผํ•œ๋‹ค.

$ npm install redux
$ npx i redux
$ yarn add redux

๊ฐ๊ฐ ํŒจํ‚ค์ง€ ๊ด€๋ฆฌ์ž์— ๋งž๊ฒŒ ์„ค์น˜ํ•ด์ฃผ๊ณ  ์‹œ์ž‘ํ•˜์ž.

Store

๋ฆฌ๋•์Šค ํŒจํ‚ค์ง€๋ฅผ ์„ค์น˜ํ•˜๋ฉด ์šฐ๋ฆฌ๋Š” ๋ฆฌ๋•์Šค์—์„œ createStore๋ผ๋Š” ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

 

import { createStore } from "redux";

์ด createStore๋Š” ํ•จ์ˆ˜๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋„ฃ์–ด์ฃผ๋Š” ์ €์žฅ์†Œ์˜ ์—ญํ• ์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.

 

์šฐ๋ฆฌ ์•ฑ์—์„œ ๋ฐ์ดํ„ฐ๋ผ๊ณ  ํ•œ๋‹ค๋ฉด ๋ณดํ†ต State๋ฅผ ๋ฐ์ดํ„ฐ๋ผ๊ณ  ํ•˜๋Š”๋ฐ, ์ •ํ™•ํžˆ State๊ฐ€ ๋ญ”์ง€ ํ•œ ๋ฒˆ ์ด์•ผ๊ธฐ ํ•ด๋ณด์ž.

State๋Š” Modified๋˜๋Š” Data ์ด๋‹ค.

์–ด๋–ค ๊ฐ’์ด ๋ณ€ํ•˜๋ฉด ๊ทธ ๊ฐ’์— ๋”ฐ๋ผ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ณด์—ฌ์ง€๋Š” ๋ถ€๋ถ„์ด ๋‹ฌ๋ผ ์ง€๊ฒŒ ํ•˜๋Š”๊ฒŒ ๋ฆฌ์•กํŠธ์—์„œ์˜ State์˜€์œผ๋ฉด Redux์˜ State ๋„ ๋˜‘๊ฐ™๋‹ค.

 

๋งŒ์•ฝ์— ์šฐ๋ฆฌ๊ฐ€ ์นด์šดํ„ฐ ์•ฑ์„ ๋งŒ๋“ ๋‹ค๊ณ  ์น˜๋ฉด ์˜ฌ๋ผ๊ฐ€๋Š” ์ˆซ์ž๊ฐ€ state๊ฐ€ ๋˜๋Š” ๊ฑฐ๋‹ค.

 

์ด๋Ÿฐ state๋ฅผ store์— ์ง‘์–ด ๋„ฃ๋Š” ๊ฒƒ์ด๋‹ค.

 

๊ทธ๋ฆฌ๊ณ  ๊ทธ๊ฑธ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•˜๋Š” ๊ฒƒ์ด ๋ฐ”๋กœ createState์ด๊ณ .

 

ํ•˜์ง€๋งŒ ์—ฌ๊ธฐ์„œ store์— createStore state๋ฅผ ๋„ฃ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ state๋ฅผ ๋ณ€๊ฒฝ์‹œํ‚ค๋Š” ํ•จ์ˆ˜๋ฅผ ๋„ฃ์–ด์•ผ ํ•œ๋‹ค.

 

๊ทธ ํ•จ์ˆ˜๊ฐ€ ๋ฐ”๋กœ reducer๊ฐ€ ๋˜๋Š” ๊ฒƒ์ด๋‹ค.

const reducer = () => {};

const store = createStore(reducer);

๊ทธ๋ฆฌ๊ณ  ์ด๋Ÿฐ store๋ฅผ ์ฝ˜์†”๋กœ ์ถœ๋ ฅํ•˜๋ฉด 4๊ฐ€์ง€์˜ ํ•จ์ˆ˜๊ฐ€ ๋‚˜์˜จ๋‹ค.

const reducer = () => {};

const store = createStore(reducer);

console.log(store);

>>> dispatch, subscribe, getState, replaceReducer

์—ฌ๊ธฐ์„œ replaceReducer๋Š” ์ž ๊น ์ œ์ณ๋‘๊ณ  ์•ž์˜ 3๊ฐœ๋ฅผ ์ง‘์ค‘ํ•ด๋ณด์ž.

 

  • dispatch : ๋’ค์— ๋‚˜์˜ฌ dispatch๋กœ ์ž ๊น ์ด์•ผ๊ธฐ ํ•˜์ž๋ฉด action์„ ๋ฐœ์ƒ์‹œ์ผœ state๋ฅผ ๋ณ€ํ•˜๊ฒŒ ๋งŒ๋“œ๋Š” ์žฅ๋ณธ์ธ
  • subscribe : state ๊ฐ’์ด ๋ณ€ํ•˜๋Š”์ง€ ๊ฐ์‹œํ•˜๋Š” cctv ๊ฒฉ
  • getState : state๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๋Š” getter ํ•จ์ˆ˜

๊ทธ๋Ÿผ ์šฐ๋ฆฌ๋Š” ๋ฆฌ๋•์Šค์˜ store๋ฅผ ๋งŒ๋“ค์—ˆ๋‹ค.

reducer

reducer๋Š” ์•ž์„œ ๋ง ํ–ˆ๋˜ ๊ฒƒ ์ฒ˜๋Ÿผ ํ•จ์ˆ˜์ด๋‹ค.


์–ด๋–ค ํ•จ์ˆ˜์ผ๊นŒ?


๋ฐ”๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์ •ํ•˜๋Š” ํ•จ์ˆ˜์ด๋‹ค.


์œ„์—์„œ ์šฐ๋ฆฌ๊ฐ€ ๋ฐ์ดํ„ฐ์™€ state๋ฅผ ๋ถ„๋ฆฌํ•ด์„œ ์ƒ๊ฐํ–ˆ๋Š”๋ฐ, data๋ณด๋‹ค ๋” ๊ตฌ์ฒด์ ์ธ ๊ฒƒ์ด state์ด๋ผ๊ณ  ํ–ˆ๋‹ค.

 

state๋Š” ๋ณ€ํ•˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๋œปํ•˜๊ณ  ์ด reducer ํ•จ์ˆ˜๋Š” ๋ฐ”๋กœ state๋ฅผ ๋ณ€๊ฒฝ์‹œํ‚ค๋Š” ํ•จ์ˆ˜์ด๋‹ค.


์ด ํ•จ์ˆ˜๊ฐ€ return ํ•˜๋Š” ๊ฐ’์ด ๋ฐ”๋กœ state๊ฐ€ ๋˜๋Š” ๊ฒƒ์ด๋‹ค.

 

๋งŒ์•ฝ ๋‚ด๊ฐ€ ๋ฆฌ๋“€์„œ ํ•จ์ˆ˜์— ๋ฐ˜ํ™˜์œผ๋กœ "Hello"๋ผ๋Š” ์ŠคํŠธ๋ง์„ ์ค€๋‹ค๋ฉด store์— ์žˆ๋Š” state๋Š” Hello๊ฐ€ ๋œ๋‹ค.

const reducer = () => {
    return "hello";
}

const store = createStore(reducer);

console.log(store.getState());

>>> hello

ํ˜น์€

const reducer = (state = 0) => {
    return state;
}
const store = createStore(reducer);
console.log(store.getState());

>>> 0

์ด๋ ‡๊ฒŒ๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ, ์—ฌ๊ธฐ์„œ ์šฐ๋ฆฌ๋Š” ์–ด๋–ป๊ฒŒ reducer๋ฅผ ์‚ฌ์šฉํ•˜๋ƒ?

 

  1. reducer์—๊ฒŒ ์ธ์ž๋ฅผ ๋„˜๊ธด๋‹ค.
  2. reducer๋Š” ์ธ์ž๋ฅผ ๋ฐ›๊ณ  ์–ด๋–ค ๋กœ์ง์„ ์‹คํ–‰์‹œํ‚ฌ์ง€ ๊ฒฐ์ •ํ•œ๋‹ค.
  3. ํ•ด๋‹น ๋กœ์ง์„ ์ˆ˜ํ–‰ํ•œ ๊ฒฐ๊ณผ๋กœ state๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
  4. ๋ฐ˜ํ™˜๋œ state๋Š” ์šฐ๋ฆฌ์˜ ์ƒˆ๋กœ์šด state๊ฐ€ ๋œ๋‹ค.

์—ฌ๊ธฐ์„œ ๋งํ•˜๋Š” ์ธ์ž๋Š” ๋ฐ”๋กœ Action์ด๋‹ค.

Action

๋งŒ์•ฝ ์šฐ๋ฆฌ๊ฐ€ ์นด์šดํŒ…ํ•˜๋Š” ์•ฑ์„ ๋งŒ๋“ ๋‹ค๊ณ  ํ•˜๋ฉด reducer์—์„œ state + 1์ด๋‚˜ state - 1์„ ์ˆ˜ํ–‰ํ•ด์•ผ ๋˜๋Š”๋ฐ, ์–˜๋“ค์„ ์–ด๋–ป๊ฒŒ ๊ตฌ๋ถ„ํ• ๊นŒ?

 

๋ฐ”๋กœ Action์œผ๋กœ ๊ตฌ๋ถ„ํ•œ๋‹ค.

const reducer = (state, action) => {
    return state;
}

const store = createStore(reducer);

reducer์˜ ๋‘ ๋ฒˆ์งธ ์ธ์ž๋กœ Action์ด ๋“ค์–ด๊ฐ€๋Š”๋ฐ, ์ด Action์€ ์šฐ๋ฆฌ๊ฐ€ reducer์™€ ์†Œํ†ตํ•˜๋Š” ๋งค๊ฐœ์ฒด์ด๋‹ค.

 

reducer์—๊ฒŒ ์–ด๋–ค ์ผ์„ ํ• ์ง€ Action์œผ๋กœ ๋Œ€ํ™”ํ•˜๋Š”๊ฑฐ๊ณ  reducer๋Š” action์— ๋”ฐ๋ผ์„œ returnํ•ด์ฃผ๋Š”๊ฑฐ๋‹ค.

 

๊ทธ๋Ÿผ ์ด action์„ ์–ด๋–ป๊ฒŒ ์ „๋‹ฌํ•ด์ฃผ๋ƒ๊ณ ?

 

๋ฐ”๋กœ Dispatch์ด๋‹ค.

Dispatch

์•ž์—์„œ ์šฐ๋ฆฌ๊ฐ€ store๋ฅผ ์ฝ˜์†”๋กœ ์ถœ๋ ฅํ•˜๋ฉด dispatch๊ฐ€ ๋‚˜์˜ค๋Š”๊ฒƒ์„ ํ™•์ธ ํ–ˆ์„ ๊ฒƒ์ด๋‹ค.

 

๊ทธ dispatch๋ฅผ ์ด์šฉํ•ด์„œ ์šฐ๋ฆฌ๋Š” action์„ ์ „๋‹ฌํ•œ๋‹ค. store.dispatch() ์˜ ๋งค๊ฐœ๋ณ€์ˆ˜์— ์–ด๋–ค Action์ธ์ง€ ๊ฐ์ฒด ํ˜•ํƒœ๋กœ ๋ณด๋‚ด์ค€๋‹ค.

const reducer = (state, action) => {
  return state;
}
const store = createStore(reducer);

store.dispatch({type: "ADD"})

๊ทธ๋ฆฌ๊ณ  ์—ฌ๊ธฐ์„œ ์กฐ๊ฑด์„ ์กฐ๊ธˆ ์ถ”๊ฐ€ํ•ด๋ณด์ž๋ฉด

const reducer = (state = 0, action) => {
  if(action.type === "ADD") { return state + 1;}
  else return state;
}
const store = createStore(reducer);

store.dispatch({type: "ADD"});
store.dispatch({type: "ADD"});
store.dispatch({type: "ADD"});
store.dispatch({type: "ADD"});

console.log(store.getState());

>>> 4

๊ฐ€ ๋œ๋‹ค.

 

๋‚ด๊ฐ€ ADD๋ผ๋Š” Action์„ ๊ฐ–๋Š” dispatch๋ฅผ ์ด 4๋ฒˆ ํ˜ธ์ถœํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— 4๊ฐ€ ์ถœ๋ ฅ๋˜๋Š” ๊ฒƒ์ด๋‹ค.

Subscribe

Subscribe๋Š” ๋ณ€ํ™”๋ฅผ ๊ฐ์ง€ํ•œ๋‹ค.

 

Dispatch๋ฅผ ํ†ตํ•ด์„œ Reducer์˜ state๋ฅผ ๋ณ€๊ฒฝ์‹œํ‚ฌ ๋•Œ ๋งˆ๋‹ค Subscribe๋Š” ์›€์ฐ”์›€์ฐ”ํ•˜๋Š”๋ฐ, ๊ทธ ์›€์ฐ”์›€์ฐ”์„ ํ†ตํ•ด์„œ ์šฐ๋ฆฌ๋Š” ๋ณ€ํ™”๋ฅผ ๊ฐ์ง€ํ•œ๋‹ค.

 

Subscribe ์—ญ์‹œ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ํ•จ์ˆ˜๊ฐ€ ๋“ค์–ด๊ฐ€๊ฒŒ ๋˜๋Š”๋ฐ, ๊ทธ ํ•จ์ˆ˜๋Š” ๋ณ€ํ™”๊ฐ€ ์žˆ์„ ๋•Œ ์–ด๋–ค ํ–‰๋™์„ ํ• ์ง€์— ๋Œ€ํ•œ ํ•จ์ˆ˜์ด๋‹ค.

 

๋งŒ์•ฝ ๋‚ด๊ฐ€

const reducer = (state = 0, action) => {
  if(action.type === "ADD") state + 1;
  return state;
}
const store = createStore(reducer);

store.dispatch({type: "ADD"})

const onChange() => {
  console.log("changed");
}

store.subscribe(onChnage);

์ด๋ ‡๊ฒŒ ์ฃผ๋ฉด

const reducer = (state = 0, action) => {
  if(action.type === "ADD") state + 1;
  return state;
}
const store = createStore(reducer);

const onChange() => {
  console.log("changed");
}

store.subscribe(onChnage);

store.dispatch({type: "ADD"})
store.dispatch({type: "ADD"})
store.dispatch({type: "ADD"})
store.dispatch({type: "ADD"})
store.dispatch({type: "ADD"})

>>> changed
>>> changed
>>> changed
>>> changed
>>> changed

๋ณ€ํ™”๊ฐ€ ๊ฐ์ง€๋  ๋•Œ ๋งˆ๋‹ค subscribe๊ฐ€ ํ˜ธ์ถœ๋œ๋‹ค.


์ž ์ด๋ ‡๊ฒŒ ์˜ค๋Š˜์€ Redux์˜ ํ•ต์‹ฌ ์ปจ์…‰๊ณผ 5ํ˜•์ œ์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณด์•˜๋‹ค.

 

์‚ฌ์‹ค ๋‹ค๋ฅธ ๊ธ€์€ ์ง์ ‘ ํƒ€์ดํ•‘ ํ•˜๋Š” ๊ฒƒ์„ ์ถ”์ฒœํ•˜์ง€๋งŒ ์ด๋ฒˆ ๊ธ€์€ ๊ทธ๋ƒฅ ๋”ฐ๋ผ์˜ค๋Š” ๊ฒƒ์„ ์ถ”์ฒœํ•œ๋‹ค.

 

๋งŒ์•ฝ ๋‹น์‹ ์ด ๋ฆฌ๋•์Šค์— ๋Œ€ํ•ด์„œ ์ฒ˜์Œ ์•Œ๊ฒŒ ๋˜์—ˆ๋‹ค๋ฉด ํƒ€์ž๋ฅผ ์น˜๋Š๋ผ ํ•ต์‹ฌ์„ ๋†“์น ๊ฒƒ์ด ๋‘๋ ค์›Œ์„œ์ด๋‹ค.

 

๋‚ด ๋ธ”๋กœ๊ทธ๋งŒ ๋ณด๊ณ  ๊ณต๋ถ€๋ฅผ ํ•˜๋Š” ์‚ฌ๋žŒ์€ ์—†๊ฒ ์ง€๋งŒ ๋…ธํŒŒ์‹ฌ์— ๋ง ํ•˜์ž๋ฉด ๋‹ค๋ฅธ ๋ธ”๋กœ๊ทธ๋„ ์ถฉ๋ถ„ํžˆ ๋ด์•ผํ•œ๋‹ค.

 

๊ณต์‹ ๋ฌธ์„œ๋ผ๋ฉด ๋” ์ข‹๊ณ .

๋Œ“๊ธ€