[DevCamp] ๐Ÿ”ฅ Firebase์™€ Redux Store ํ•จ๊ป˜ ์ดํ•ดํ•˜๊ธฐ

๋™๊ฑดยท2025๋…„ 4์›” 15์ผ
0

DevCamp

๋ชฉ๋ก ๋ณด๊ธฐ
48/85

๐Ÿ”ฅ Firebase์™€ Redux Store ํ•จ๊ป˜ ์ดํ•ดํ•˜๊ธฐ

React์—์„œ ์ƒํƒœ ๊ด€๋ฆฌ๋ฅผ ํ•  ๋•Œ Redux๋ฅผ ์“ฐ๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ๊ณ ,
๋ฐฑ์—”๋“œ ์—†์ด ๋น ๋ฅด๊ฒŒ ์„œ๋ฒ„ ๊ธฐ๋Šฅ์„ ๋ถ™์ผ ๋• Firebase๊ฐ€ ์œ ์šฉํ•˜๋‹ค.
๊ทธ๋Ÿฐ๋ฐ ์ด ๋‘˜์„ ํ•จ๊ป˜ ์“ธ ๋•Œ ๊ตฌ์กฐ๋ฅผ ์–ด๋–ป๊ฒŒ ์žก์•„์•ผ ํ• ์ง€ ๊ณ ๋ฏผ์ด ์ƒ๊ธฐ๊ธฐ ๋งˆ๋ จ์ด๋‹ค.

์˜ค๋Š˜์€ Firebase์™€ Redux Store๊ฐ€ ๊ฐ๊ฐ ์–ด๋–ค ์—ญํ• ์„ ํ•˜๊ณ ,
์–ด๋–ป๊ฒŒ ํ•จ๊ป˜ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์ •๋ฆฌํ•ด๋ณธ๋‹ค.


Firebase๋ž€?

Firebase๋Š” Google์—์„œ ์ œ๊ณตํ•˜๋Š” BaaS(Backend as a Service)๋กœ,
๋ฐฑ์—”๋“œ ํ™˜๊ฒฝ ์—†์ด๋„ ์‰ฝ๊ฒŒ ์„œ๋ฒ„ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

์ฃผ์š” ๊ธฐ๋Šฅ์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค:

  • Authentication (๋กœ๊ทธ์ธ/ํšŒ์›๊ฐ€์ž…)
  • Firestore (์‹ค์‹œ๊ฐ„ NoSQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค)
  • Storage (ํŒŒ์ผ ์ €์žฅ)
  • Hosting
  • Cloud Functions (์„œ๋ฒ„๋ฆฌ์Šค ํ•จ์ˆ˜)

Firebase๋ฅผ ์“ฐ๋ฉด ํ”„๋ก ํŠธ์—”๋“œ์—์„œ ๋ฐ”๋กœ ๋กœ๊ทธ์ธ, ๋ฐ์ดํ„ฐ ์ €์žฅ, ํŒŒ์ผ ์—…๋กœ๋“œ ๋“ฑ์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.


Redux Store๋ž€?

Redux๋Š” React์˜ ์ƒํƒœ ๊ด€๋ฆฌ๋ฅผ ๋” ์ฒด๊ณ„์ ์œผ๋กœ ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋„์™€์ฃผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋‹ค.

Redux Store๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ „์ฒด์˜ ์ƒํƒœ๋ฅผ ์ค‘์•™ ์ง‘์ค‘ํ™”ํ•ด ๊ด€๋ฆฌํ•˜๋Š” ๊ณต๊ฐ„์ด๋‹ค.

import { createStore } from 'redux';
import rootReducer from './reducers';

const store = createStore(rootReducer);

Redux Store๋Š” ํฌ๊ฒŒ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ตฌ์„ฑ์š”์†Œ๋กœ ๋‚˜๋‰œ๋‹ค:

  • Action: ๋ฌด์—‡์„ ํ• ์ง€ ์„ค๋ช…ํ•˜๋Š” ๊ฐ์ฒด
  • Reducer: ์•ก์…˜์— ๋”ฐ๋ผ ์ƒํƒœ๋ฅผ ์–ด๋–ป๊ฒŒ ๋ฐ”๊ฟ€์ง€ ์ •์˜
  • Store: ์ƒํƒœ์™€ ์•ก์…˜, ๋ฆฌ๋“€์„œ๋ฅผ ์—ฐ๊ฒฐํ•œ ์ค‘์•™ ์ €์žฅ์†Œ

Firebase + Redux ํ•จ๊ป˜ ์“ฐ๊ธฐ

๋‘ ๊ฐœ๋ฅผ ๊ฐ™์ด ์“ฐ๋ฉด ์ด๋ ‡๊ฒŒ ๋‚˜๋ˆŒ ์ˆ˜ ์žˆ๋‹ค:

์—ญํ• ์‚ฌ์šฉ ๋„๊ตฌ
์‚ฌ์šฉ์ž ์ธ์ฆFirebase Auth
๋ฐ์ดํ„ฐ ์ €์žฅ/์ฝ๊ธฐFirebase Firestore
๋กœ์ปฌ ์ƒํƒœ ๊ด€๋ฆฌRedux Store
์ „์—ญ ์ƒํƒœ ๊ด€๋ฆฌRedux Store

์ฆ‰, Firebase๋Š” ๋ฐฑ์—”๋“œ ์—ญํ• , Redux๋Š” ํ”„๋ก ํŠธ์—”๋“œ ์ƒํƒœ ๊ด€๋ฆฌ ์—ญํ• ์„ ๋‹ด๋‹นํ•œ๋‹ค.


์˜ˆ์‹œ: ๋กœ๊ทธ์ธ ์ƒํƒœ Redux์— ์ €์žฅํ•˜๊ธฐ

  1. Firebase๋กœ ๋กœ๊ทธ์ธ ์ฒ˜๋ฆฌ
import { signInWithEmailAndPassword } from 'firebase/auth';
import { auth } from './firebase'; // ์ดˆ๊ธฐํ™”๋œ Firebase auth ์ธ์Šคํ„ด์Šค

export const loginWithFirebase = async (email, password) => {
  const userCredential = await signInWithEmailAndPassword(auth, email, password);
  return userCredential.user;
};
  1. Redux์— ๋กœ๊ทธ์ธ ์ •๋ณด ์ €์žฅ
// actions/userActions.ts
export const setUser = (user) => ({
  type: 'SET_USER',
  payload: user,
});
// reducers/userReducer.ts
const initialState = {
  currentUser: null,
};

export default function userReducer(state = initialState, action) {
  switch (action.type) {
    case 'SET_USER':
      return { ...state, currentUser: action.payload };
    default:
      return state;
  }
}
  1. ๋กœ๊ทธ์ธ ํ›„ Redux์— ์ €์žฅ
const handleLogin = async () => {
  const user = await loginWithFirebase(email, password);
  dispatch(setUser(user));
};

์ด๋Ÿฐ ์‹์œผ๋กœ Firebase์—์„œ ๋ฐ›์€ ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ Redux์— ์ €์žฅํ•ด ์ „์—ญ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.


์ฃผ์˜ํ•  ์ 

  • Redux์—๋Š” ๋ฏผ๊ฐํ•œ ์ •๋ณด๋ฅผ ์ €์žฅํ•˜์ง€ ์•Š๋Š”๋‹ค. (์˜ˆ: ๋น„๋ฐ€๋ฒˆํ˜ธ, ํ† ํฐ ๋“ฑ)
  • Firebase ์ž์ฒด์ ์œผ๋กœ onAuthStateChanged์™€ ๊ฐ™์€ ๋ฆฌ์Šค๋„ˆ๋„ ์žˆ์œผ๋ฏ€๋กœ,
    Redux์™€ ํ˜ผ๋™ํ•˜์ง€ ์•Š๋„๋ก ์—ญํ• ์„ ์ž˜ ๊ตฌ๋ถ„ํ•ด์•ผ ํ•œ๋‹ค.
  • ์ƒํƒœ ๋™๊ธฐํ™”๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ, Firestore์˜ onSnapshot๊ณผ Redux์˜ dispatch๋ฅผ ํ•จ๊ป˜ ํ™œ์šฉํ•˜๋ฉด ์ข‹๋‹ค.

๐Ÿ”จ TIL

  • Firebase๋Š” ์ธ์ฆ, DB, ์ €์žฅ์†Œ ๋“ฑ ๋ฐฑ์—”๋“œ ๊ธฐ๋Šฅ์„ ๋Œ€์‹ ํ•ด์ฃผ๋Š” ํ”Œ๋žซํผ์ด๋‹ค.
  • Redux Store๋Š” ํ”„๋ก ํŠธ์—”๋“œ์˜ ์ƒํƒœ๋ฅผ ์ „์—ญ์—์„œ ์ผ๊ด€๋˜๊ฒŒ ๊ด€๋ฆฌํ•˜๊ฒŒ ๋„์™€์ค€๋‹ค.
  • Firebase์—์„œ ๋ฐ›์€ ๋ฐ์ดํ„ฐ๋ฅผ Redux Store์— ์ €์žฅํ•˜๋ฉด ์ „์—ญ ์ƒํƒœ์™€ ์„œ๋ฒ„ ์ƒํƒœ๋ฅผ ์ž˜ ์—ฐ๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ๋‹จ, Redux๋Š” ํด๋ผ์ด์–ธํŠธ ์ƒํƒœ ๊ด€๋ฆฌ๋งŒ ํ•˜๋ฏ€๋กœ ๋ณด์•ˆ ์ •๋ณด๋ฅผ ์ €์žฅํ•˜์ง€ ์•Š๋„๋ก ์ฃผ์˜ํ•ด์•ผ ํ•œ๋‹ค.
profile
๋ฐฐ๊ณ ํ”ˆ ๊ฐœ๋ฐœ์ž

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