Redux

2025. 4. 1. 00:41Frameworks/React

Redux

Redux는 JavaScript 애플리케이션을 위한 예측 가능한 상태 컨테이너로, React에 국한되지 않지만 React와 함께 가장 많이 사용됩니다.

Redux의 핵심 원칙

  1. 단일 진실 소스(Single Source of Truth): 애플리케이션의 모든 상태는 하나의 스토어(store)에 저장
  2. 상태는 읽기 전용(State is Read-Only): 상태를 변경하는 유일한 방법은 액션(action)을 dispatch하는 것
  3. 변경은 순수 함수로 작성(Changes are Made with Pure Functions): 리듀서(reducer)는 이전 상태와 액션을 받아 다음 상태를 반환하는 순수 함수

Redux의 주요 개념

  1. 액션(Action): 어떤 일이 일어났는지 설명하는 객체
  2. 리듀서(Reducer): 이전 상태와 액션에 따라 새 상태를 계산하는 함수
  3. 스토어(Store): 애플리케이션의 상태를 보관하는 객체
  4. 디스패치(Dispatch): 액션을 스토어에 보내는 함수
  5. 구독(Subscribe): 상태 변화를 감지하는 메커니즘

Redux 설치

npm install redux react-redux

또는

yarn add redux react-redux

Redux 사용 방법

1. 액션 타입과 액션 생성자 정의

// actions/userActions.js

// 액션 타입
export const LOGIN = 'LOGIN';
export const LOGOUT = 'LOGOUT';

// 액션 생성자
export const login = (userData) => ({
  type: LOGIN,
  payload: userData
});

export const logout = () => ({
  type: LOGOUT
});

2. 리듀서 작성

// reducers/userReducer.js
import { LOGIN, LOGOUT } from '../actions/userActions';

const initialState = {
  user: null,
  isAuthenticated: false
};

function userReducer(state = initialState, action) {
  switch (action.type) {
    case LOGIN:
      return {
        ...state,
        user: action.payload,
        isAuthenticated: true
      };
    case LOGOUT:
      return {
        ...state,
        user: null,
        isAuthenticated: false
      };
    default:
      return state;
  }
}

export default userReducer;

3. 루트 리듀서 생성 (여러 리듀서를 결합)

// reducers/index.js
import { combineReducers } from 'redux';
import userReducer from './userReducer';
import postsReducer from './postsReducer';

const rootReducer = combineReducers({
  user: userReducer,
  posts: postsReducer
});

export default rootReducer;

4. 스토어 생성

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

const store = createStore(
  rootReducer,
  // Redux DevTools Extension 사용 설정 (선택 사항)
  window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
);

export default store;

5. Provider로 애플리케이션 감싸기

// index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import { Provider } from 'react-redux';
import store from './store';
import App from './App';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <Provider store={store}>
    <App />
  </Provider>
);

6. 컴포넌트에서 Redux 상태 사용

// components/LoginPage.js
import React, { useState } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { login } from '../actions/userActions';

function LoginPage() {
  const [username, setUsername] = useState('');
  const [password, setPassword] = useState('');
  
  // Redux 상태 접근
  const { user, isAuthenticated } = useSelector(state => state.user);
  // 디스패치 함수 가져오기
  const dispatch = useDispatch();

  const handleSubmit = (e) => {
    e.preventDefault();
    // 액션 디스패치
    dispatch(login({ username }));
  };

  if (isAuthenticated) {
    return <p>이미 로그인되었습니다, {user.username}님!</p>;
  }

  return (
    <form onSubmit={handleSubmit}>
      <h2>로그인</h2>
      <input
        type="text"
        placeholder="사용자명"
        value={username}
        onChange={(e) => setUsername(e.target.value)}
      />
      <input
        type="password"
        placeholder="비밀번호"
        value={password}
        onChange={(e) => setPassword(e.target.value)}
      />
      <button type="submit">로그인</button>
    </form>
  );
}

export default LoginPage;
// components/Dashboard.js
import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { logout } from '../actions/userActions';

function Dashboard() {
  const { user, isAuthenticated } = useSelector(state => state.user);
  const dispatch = useDispatch();

  if (!isAuthenticated) {
    return <p>대시보드를 보려면 로그인하세요.</p>;
  }

  return (
    <div>
      <h2>대시보드</h2>
      <p>안녕하세요, {user.username}님!</p>
      <button onClick={() => dispatch(logout())}>로그아웃</button>
    </div>
  );
}

export default Dashboard;

Redux 미들웨어

미들웨어는 Redux의 기능을 확장하는 방법으로, 주로 비동기 작업이나 로깅 등에 사용됩니다. 가장 많이 사용되는 Redux 미들웨어는 다음과 같습니다:

  1. redux-thunk: 액션 생성자가 함수를 반환할 수 있게 해주어 비동기 작업 처리
  2. redux-saga: 복잡한 비동기 흐름을 더 쉽게 관리
  3. redux-logger: 액션과 상태 변화를 콘솔에 기록

redux-thunk 예제

npm install redux-thunk
// store.js
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from './reducers';

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

export default store;
// actions/userActions.js
export const LOGIN_REQUEST = 'LOGIN_REQUEST';
export const LOGIN_SUCCESS = 'LOGIN_SUCCESS';
export const LOGIN_FAILURE = 'LOGIN_FAILURE';

// 비동기 액션 생성자
export const loginUser = (credentials) => {
  return async (dispatch) => {
    dispatch({ type: LOGIN_REQUEST });
    
    try {
      // API 호출
      const response = await fetch('/api/login', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(credentials)
      });
      
      if (!response.ok) {
        throw new Error('로그인 실패');
      }
      
      const userData = await response.json();
      dispatch({
        type: LOGIN_SUCCESS,
        payload: userData
      });
    } catch (error) {
      dispatch({
        type: LOGIN_FAILURE,
        payload: error.message
      });
    }
  };
};

 

'Frameworks > React' 카테고리의 다른 글

Context API vs Redux  (0) 2025.04.01
Redux Toolkit  (0) 2025.04.01
React 상태 관리  (0) 2025.04.01
복잡한 라우팅 구성 예제  (0) 2025.04.01
React Router의 주요 기능 상세 설명  (0) 2025.04.01