Front-end/React

[React] Redux Middleware: ๋ฆฌ๋•์Šค์˜ ์ˆจ์€ ์˜์›…๋“ค ๐Ÿฆธ‍โ™‚๏ธ๐Ÿฆธ‍โ™€๏ธ

xeunnie 2025. 1. 10. 01:00
728x90
๋ฐ˜์‘ํ˜•

Redux Middleware ํ†บ์•„๋ณด๊ธฐ! ๐Ÿฆธ‍โ™‚๏ธ๐Ÿฆธ‍โ™€๏ธ

Redux๋ฅผ ์‚ฌ์šฉํ•˜๋‹ค ๋ณด๋ฉด, ๋‹จ์ˆœํžˆ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๊ฑธ ๋„˜์–ด ๋” ๋ณต์žกํ•œ ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•  ๋•Œ๊ฐ€ ์žˆ์–ด์š”. ์˜ˆ๋ฅผ ๋“ค์–ด, ๋น„๋™๊ธฐ API ํ˜ธ์ถœ์ด๋‚˜ ๋กœ๊ทธ ์ถœ๋ ฅ ๊ฐ™์€ ์ผ์„ ๋ง์ด์ฃ . ๋ฐ”๋กœ ์—ฌ๊ธฐ์„œ Redux Middleware๊ฐ€ ๋“ฑ์žฅํ•ฉ๋‹ˆ๋‹ค.

 

Middleware๋Š” ๋งˆ์น˜ ์•ก์…˜๊ณผ ๋ฆฌ๋“€์„œ ์‚ฌ์ด์—์„œ ์ผ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋น„๋ฐ€ ์š”์› ๊ฐ™์•„์š”. ์˜ค๋Š˜์€ ์ด ์š”์›์„ ์ œ๋Œ€๋กœ ์ดํ•ดํ•˜๊ณ , ์‹ค๋ฌด์—์„œ๋„ ์œ ์šฉํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํŒํŒ ์•Œ๋ ค๋“œ๋ฆด๊ฒŒ์š”. ๐Ÿ˜Š


๐Ÿ” Middleware๋ž€ ๋ฌด์—‡์ผ๊นŒ?

Redux์—์„œ Middleware๋Š” ์•ก์…˜์ด ๋ฆฌ๋“€์„œ์— ๋„๋‹ฌํ•˜๊ธฐ ์ „์— ์ค‘๊ฐ„์—์„œ ๊ฐ€๋กœ์ฑ„๊ณ  ์ถ”๊ฐ€ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋„๊ตฌ์ž…๋‹ˆ๋‹ค.

 

์‰ฝ๊ฒŒ ๋งํ•ด:

  1. ์•ก์…˜์ด ๋””์ŠคํŒจ์น˜(dispatch)๋˜๋ฉด,
  2. Middleware๊ฐ€ ๊ทธ ์•ก์…˜์„ ๊ฐ€๋กœ์ฑ„,
  3. ๋ญ”๊ฐ€ ์ž‘์—…์„ ํ•œ ๋’ค์— ๋ฆฌ๋“€์„œ๋กœ ๋„˜๊ธฐ๊ฑฐ๋‚˜, ๋„˜๊ธฐ์ง€ ์•Š๊ฑฐ๋‚˜(!) ํ•  ์ˆ˜ ์žˆ์ฃ .

โœจ ๋น„์œ : Middleware๋Š” ํƒ๋ฐฐ๋ฅผ ์ค‘๊ฐ„์— ๊ฐ€๋กœ์ฑ„์„œ ๋ฌผ๊ฑด์„ ํ™•์ธํ•˜๊ณ , ํฌ์žฅ์ง€๋ฅผ ๋ฐ”๊ฟ” ๋‹ค์‹œ ๋ฐฐ๋‹ฌํ•˜๋Š” ํƒ๋ฐฐ ์‹ฌ์‚ฌ๊ด€์ด์—์š”. ๐Ÿ“ฆ


๐Ÿ”ฆ Middleware์˜ ์ฃผ์š” ์—ญํ• 

Middleware๊ฐ€ ์—†์œผ๋ฉด Redux๋Š” ์ •๋ง ๋‹จ์ˆœํ•œ ์ƒํƒœ ๊ด€๋ฆฌ ๋„๊ตฌ์ผ ๋ฟ์ด์—์š”. Middleware ๋•๋ถ„์— Redux๋Š” ๋‹ค์–‘ํ•œ ์ผ์„ ํ•  ์ˆ˜ ์žˆ์ฃ 

1๏ธโƒฃ ๋น„๋™๊ธฐ ์ž‘์—… ์ฒ˜๋ฆฌ

API ์š”์ฒญ์ด๋‚˜ ํƒ€์ด๋จธ ๊ฐ™์€ ์ž‘์—…์„ ๋น„๋™๊ธฐ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์–ด์š”.

2๏ธโƒฃ ๋กœ๊น…

๋””๋ฒ„๊น…์„ ์œ„ํ•ด ์•ก์…˜๊ณผ ์ƒํƒœ๋ฅผ ๋กœ๊น…ํ•  ์ˆ˜ ์žˆ์–ด์š”.

3๏ธโƒฃ ์กฐ๊ฑด๋ถ€ ์•ก์…˜ ์ฒ˜๋ฆฌ

ํŠน์ • ์กฐ๊ฑด์— ๋”ฐ๋ผ ์•ก์…˜์„ ๋ง‰๊ฑฐ๋‚˜, ์ƒˆ๋กœ์šด ์•ก์…˜์„ ์ถ”๊ฐ€๋กœ ๋””์ŠคํŒจ์น˜ํ•  ์ˆ˜ ์žˆ์–ด์š”.

4๏ธโƒฃ ์ถ”๊ฐ€์ ์ธ ์•ก์…˜ ์ƒ์„ฑ

ํ•˜๋‚˜์˜ ์•ก์…˜์„ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์•ก์…˜์œผ๋กœ ๋ณ€ํ™˜ํ•˜๊ฑฐ๋‚˜, ์ž๋™์œผ๋กœ ์ƒˆ๋กœ์šด ์•ก์…˜์„ ๋””์ŠคํŒจ์น˜ํ•  ์ˆ˜ ์žˆ์–ด์š”.


โš™๏ธ Middleware์˜ ๋™์ž‘ ์›๋ฆฌ

Redux Middleware๋Š” store์˜ dispatch ๋ฉ”์„œ๋“œ๋ฅผ ํ™•์žฅํ•ด์„œ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค.

 

Middleware๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํ๋ฆ„์„ ๋”ฐ๋ฆ…๋‹ˆ๋‹ค:

  1. store: ๋ฆฌ๋•์Šค ์Šคํ† ์–ด๊ฐ€ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.
  2. dispatch(action): ์•ก์…˜์ด ๋””์ŠคํŒจ์น˜๋ฉ๋‹ˆ๋‹ค.
  3. Middleware: ์•ก์…˜์„ ๊ฐ€๋กœ์ฑ„ ์ถ”๊ฐ€ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.
  4. reducer: ๊ฐ€๊ณต๋œ ์•ก์…˜์ด ๋ฆฌ๋“€์„œ๋กœ ์ „๋‹ฌ๋ฉ๋‹ˆ๋‹ค.
  5. store: ๋ฆฌ๋“€์„œ๊ฐ€ ์ƒˆ๋กœ์šด ์ƒํƒœ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ‘ฉ๐Ÿป‍๐Ÿ’ป Middleware ์‚ฌ์šฉํ•ด๋ณด๊ธฐ

๊ธฐ๋ณธ ๋กœ๊ฑฐ(Logger) Middleware ๊ตฌํ˜„

๊ฐ€์žฅ ๊ฐ„๋‹จํ•œ ์˜ˆ๋กœ, ์•ก์…˜๊ณผ ์ƒํƒœ๋ฅผ ๋กœ๊ทธ๋กœ ์ถœ๋ ฅํ•˜๋Š” Middleware๋ฅผ ๋งŒ๋“ค์–ด๋ณผ๊ฒŒ์š”.

const loggerMiddleware = (store) => (next) => (action) => {
  console.log('๋””์ŠคํŒจ์น˜๋œ ์•ก์…˜:', action);
  const result = next(action); // ๋‹ค์Œ Middleware ๋˜๋Š” ๋ฆฌ๋“€์„œ๋กœ ์ „๋‹ฌ
  console.log('์—…๋ฐ์ดํŠธ๋œ ์ƒํƒœ:', store.getState());
  return result;
};

 

๐Ÿ‘‰ ์—ฌ๊ธฐ์„œ:

  • store: Redux ์Šคํ† ์–ด
  • next: ๋‹ค์Œ Middleware ๋˜๋Š” ๋ฆฌ๋“€์„œ
  • action: ํ˜„์žฌ ์ฒ˜๋ฆฌ ์ค‘์ธ ์•ก์…˜

์ด Middleware๋Š” ์•ก์…˜์„ ๋กœ๊ทธ๋กœ ์ถœ๋ ฅํ•˜๊ณ , ๋ฆฌ๋“€์„œ๋กœ ๋„˜๊ธด ๋’ค ์—…๋ฐ์ดํŠธ๋œ ์ƒํƒœ๋„ ์ถœ๋ ฅํ•ด์š”.


๐Ÿš€ Redux์—์„œ Middleware ์ ์šฉํ•˜๊ธฐ

 

Redux์—์„œ Middleware๋ฅผ ์ ์šฉํ•˜๋ ค๋ฉด applyMiddleware๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•ด์š”.

import { createStore, applyMiddleware } from 'redux';
import rootReducer from './reducers';
import loggerMiddleware from './middlewares/logger';

const store = createStore(
  rootReducer,
  applyMiddleware(loggerMiddleware) // ์—ฌ๊ธฐ์„œ Middleware ๋“ฑ๋ก!
);

๐Ÿ’ผ ์‹ค๋ฌด์—์„œ ํ”ํžˆ ์“ฐ๋Š” Middleware๋“ค

1๏ธโƒฃ Redux Thunk

Redux Thunk๋Š” ๋น„๋™๊ธฐ ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ ๊ฐ€์žฅ ๊ธฐ๋ณธ์ ์ธ Middleware์—์š”.

import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';

const fetchData = () => async (dispatch) => {
  dispatch({ type: 'FETCH_DATA_START' });
  const data = await fetch('/api/data').then((res) => res.json());
  dispatch({ type: 'FETCH_DATA_SUCCESS', payload: data });
};

store.dispatch(fetchData());

 

Thunk๋Š” ์•ก์…˜ ๋Œ€์‹  ํ•จ์ˆ˜๋ฅผ ๋””์ŠคํŒจ์น˜ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ค๋‹ˆ๋‹ค. ๋น„๋™๊ธฐ API ํ˜ธ์ถœ ์‹œ ์œ ์šฉํ•˜์ฃ .

 

2๏ธโƒฃ Redux Saga

Redux Saga๋Š” Thunk๋ณด๋‹ค ๋” ๊ฐ•๋ ฅํ•˜๊ณ  ๋ณต์žกํ•œ ๋น„๋™๊ธฐ ์ž‘์—… ์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•œ ๋„๊ตฌ์—์š”. yield์™€ generator๋ฅผ ํ™œ์šฉํ•ด์„œ ์ด๋ฒคํŠธ๋ฅผ ์„ ์–ธ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ต๋‹ˆ๋‹ค.

import { call, put, takeEvery } from 'redux-saga/effects';

function* fetchData() {
  const data = yield call(fetch, '/api/data');
  yield put({ type: 'FETCH_DATA_SUCCESS', payload: data });
}

function* rootSaga() {
  yield takeEvery('FETCH_DATA_REQUEST', fetchData);
}

 

3๏ธโƒฃ Redux Logger

Redux Logger๋Š” ๋กœ๊น…์— ํŠนํ™”๋œ Middleware๋กœ, ๋””๋ฒ„๊น…์— ํฐ ๋„์›€์„ ์ค˜์š”.

import logger from 'redux-logger';

const store = createStore(rootReducer, applyMiddleware(logger));

๐ŸŽ’ Middleware ๋งŒ๋“ค๊ธฐ ์‹ค์Šต

์•ก์…˜ ์ฐจ๋‹จ๊ธฐ: ํŠน์ • ์•ก์…˜์„ ๋ง‰์•„๋ณด์ž!

const blockActionMiddleware = (store) => (next) => (action) => {
  if (action.type === 'BLOCK_THIS_ACTION') {
    console.warn('์ด ์•ก์…˜์€ ์ฐจ๋‹จ๋˜์—ˆ์Šต๋‹ˆ๋‹ค:', action);
    return; // ๋ฆฌ๋“€์„œ๋กœ ์ „๋‹ฌํ•˜์ง€ ์•Š์Œ!
  }
  return next(action); // ๋‹ค๋ฅธ ์•ก์…˜์€ ์ •์ƒ ์ฒ˜๋ฆฌ
};

 

๋‹ค์ค‘ ์•ก์…˜ ์ฒ˜๋ฆฌ๊ธฐ: ํ•œ ์•ก์…˜์œผ๋กœ ์—ฌ๋Ÿฌ ์ž‘์—… ์‹คํ–‰ํ•˜๊ธฐ

const multiActionMiddleware = (store) => (next) => (action) => {
  if (Array.isArray(action)) {
    action.forEach((singleAction) => store.dispatch(singleAction));
    return;
  }
  return next(action);
};

๐ŸŒซ๏ธ Middleware์˜ ์žฅ์ ๊ณผ ํ•œ๊ณ„

์žฅ์ 

  1. ์œ ์—ฐ์„ฑ: ๋‹ค์–‘ํ•œ ์ž‘์—…์„ ์ฒ˜๋ฆฌ ๊ฐ€๋Šฅ (๋กœ๊น…, ๋น„๋™๊ธฐ, ์กฐ๊ฑด๋ถ€ ์•ก์…˜ ๋“ฑ)
  2. ํ™•์žฅ์„ฑ: ๊ธฐ์กด Redux ํ๋ฆ„์— ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š์œผ๋ฉด์„œ ๊ธฐ๋Šฅ ์ถ”๊ฐ€ ๊ฐ€๋Šฅ
  3. ์ฝ”๋“œ ๋ถ„๋ฆฌ: ์•ก์…˜๊ณผ ๋ฆฌ๋“€์„œ์˜ ์ฑ…์ž„์„ ๋ถ„๋ฆฌํ•˜์—ฌ ์ฝ”๋“œ์˜ ๊ฐ€๋…์„ฑ์„ ๋†’์ž„

ํ•œ๊ณ„

  1. ๋ณต์žก์„ฑ ์ฆ๊ฐ€: ๋„ˆ๋ฌด ๋งŽ์€ Middleware๋Š” ์œ ์ง€๋ณด์ˆ˜๋ฅผ ์–ด๋ ต๊ฒŒ ํ•  ์ˆ˜ ์žˆ์Œ
  2. ๋””๋ฒ„๊น… ๋‚œ์ด๋„: Middleware์—์„œ ๋ฐœ์ƒํ•˜๋Š” ์˜ค๋ฅ˜๋Š” ์ถ”์ ํ•˜๊ธฐ ์–ด๋ ค์šธ ์ˆ˜ ์žˆ์Œ

๐Ÿ›ค๏ธ Redux Middleware์˜ ๋ฏธ๋ž˜

Middleware๋Š” Redux ์ƒํƒœ๊ณ„์—์„œ ํ•„์ˆ˜์ ์ธ ๋„๊ตฌ์ด์ง€๋งŒ, ๋Œ€๊ทœ๋ชจ ํ”„๋กœ์ ํŠธ์—์„œ๋Š” ์ ์ ˆํžˆ ์„ ํƒํ•˜๊ณ  ์กฐํ•ฉํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ด์š”. Thunk์™€ Logger ๊ฐ™์€ ๊ฐ„๋‹จํ•œ ๋„๊ตฌ๋ถ€ํ„ฐ Saga ๊ฐ™์€ ๋ณต์žกํ•œ ๋„๊ตฌ๊นŒ์ง€, ์—ฌ๋Ÿฌ๋ถ„์˜ ํ”„๋กœ์ ํŠธ์™€ ํŒ€ ์Šคํƒ€์ผ์— ๋งž๋Š” ์„ ํƒ์„ ํ•˜์„ธ์š”!

 

๐ŸŒท์ „์„ค์˜ ๊ฐœ๋ฐœ์ž๊ฐ€ ๋˜์–ด๋ด…์‹œ๋‹น!๐ŸŒท

728x90
๋ฐ˜์‘ํ˜•