[React] Redux 사용법

해피몬·2023년 8월 13일
post-thumbnail

Redux는 주로 웹 애플리케이션에서 전역 상태를 관리하기 위해 설계되었습니다. Redux는 단일 상태 저장소(Store)를 통해 상태를 관리하며, 이로 인해 애플리케이션의 상태를 예측 가능하고 일관되게 유지할 수 있습니다.

3가지 주요 원칙

1) 단일 스토어 (Single Source of Truth)
Redux는 애플리케이션의 모든 상태를 하나의 스토어에서 관리합니다. 이를 통해 상태가 한 곳에서 관리되어 일관성을 유지할 수 있습니다.

2) 상태는 읽기 전용 (State is Read-Only)
상태를 직접 변경할 수 없으며, 상태를 변경하기 위해서는 액션(Action)을 디스패치(dispatch)해야 합니다. 이로 인해 상태 변경의 흐름이 명확해집니다.

3) 순수 리듀서 함수 (Reducers are Pure Functions)
Redux의 리듀서는 순수 함수로, 이전 상태와 액션을 받아 새로운 상태를 반환합니다. 리듀서는 동일한 입력에 대해 항상 동일한 출력을 내놓기 때문에 상태의 변화가 예측 가능해집니다.

구성 요소

1) 액션(Action)
액션은 상태에 어떤 변화가 필요한지를 설명하는 객체입니다. 액션은 type 필드를 필수로 가지며, 상태 변경에 필요한 추가 데이터를 포함할 수 있습니다.

const incrementAction = {
  type: 'INCREMENT',
  payload: 1
};

2) 액션 생성 함수(Action Creator)
액션 생성 함수는 액션을 생성하는 함수입니다. 이를 통해 액션을 좀 더 간편하게 생성하고, 필요시 파라미터를 전달할 수 있습니다.

const increment = (amount) => ({
  type: 'INCREMENT',
  payload: amount
});

3) 리듀서(Reducer)
리듀서는 상태와 액션을 인자로 받아 새로운 상태를 반환하는 함수입니다. 리듀서는 애플리케이션의 상태 변경 로직을 담당하며, 상태 변경은 순수 함수로 이루어집니다.

const initialState = { count: 0 };

function counterReducer(state = initialState, action) {
  switch (action.type) {
    case 'INCREMENT':
      return { ...state, count: state.count + action.payload };
    case 'DECREMENT':
      return { ...state, count: state.count - action.payload };
    default:
      return state;
  }
}

4) 스토어(Store)
스토어는 애플리케이션의 상태가 저장되는 장소이며, Redux의 핵심입니다. 스토어는 리듀서와 함께 초기 상태를 받아 생성되며, 현재 상태 조회, 상태 업데이트를 위한 액션 디스패치, 상태 변경을 구독하는 메서드를 제공합니다.

import { createStore } from 'redux';

const store = createStore(counterReducer);

5) 디스패치(Dispatch)
디스패치는 액션을 스토어에 전달하여 상태를 변경하는 메서드입니다. store.dispatch()를 사용해 상태 변경을 트리거합니다.

store.dispatch(increment(5));

React에서 Redux 사용하기

React 컴포넌트에서 Redux 상태와 액션을 사용하려면 useSelector와 useDispatch라는 훅을 이용합니다.

  • 상태 조회하기: useSelector
    useSelector 훅은 스토어에서 상태를 조회하는 데 사용됩니다.
  • 액션 디스패치하기: useDispatch
    useDispatch 훅은 스토어에 액션을 전달하여 상태 변경을 트리거합니다.

1) Redux와 React-Redux 설치

npm install redux react-redux

2) 액션 정의

// actions.js
export const increment = (amount) => ({
  type: 'INCREMENT',
  payload: amount
});

export const decrement = (amount) => ({
  type: 'DECREMENT',
  payload: amount
});

3) 리듀서 정의

// reducer.js
const initialState = { count: 0 };

export function counterReducer(state = initialState, action) {
  switch (action.type) {
    case 'INCREMENT':
      return { ...state, count: state.count + action.payload };
    case 'DECREMENT':
      return { ...state, count: state.count - action.payload };
    default:
      return state;
  }
}

4) 스토어 생성

// store.js
import { createStore } from 'redux';
import { counterReducer } from './reducer';

const store = createStore(counterReducer);

export default store;

5) React-Redux Provider로 스토어 연결
Provider 컴포넌트를 사용하여 React 애플리케이션에서 Redux 스토어에 접근할 수 있게 합니다. Provider는 store를 props로 받아 애플리케이션 전체에 스토어를 공급합니다.

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

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

6) React 컴포넌트에서 사용하기

// Counter.js
import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { increment, decrement } from './actions';

function Counter() {
  const count = useSelector((state) => state.count);
  const dispatch = useDispatch();

  return (
    <div>
      <h1>Count: {count}</h1>
      <button onClick={() => dispatch(increment(1))}>+</button>
      <button onClick={() => dispatch(decrement(1))}>-</button>
    </div>
  );
}

export default Counter;

Redux 장점

1) 예측 가능한 상태 관리
Redux는 모든 상태 변경이 순수 함수(리듀서)를 통해 이루어지기 때문에, 상태 변경이 일관되고 예측 가능합니다. 이는 디버깅과 상태 추적을 용이하게 해줍니다.

2) 전역 상태 관리
Redux는 단일 스토어에서 상태를 관리하기 때문에, 여러 컴포넌트에서 동일한 상태를 손쉽게 공유할 수 있습니다. 이는 특히 대규모 애플리케이션에서 유리합니다.

3) 미들웨어를 통한 확장성
Redux는 미들웨어를 통해 비동기 로직(Redux Thunk, Redux Saga)이나 로깅 등을 추가할 수 있어, 애플리케이션을 유연하게 확장할 수 있습니다.

Redux 단점

1) 보일러플레이트 코드 증가
Redux는 상태 관리 로직을 체계적으로 관리할 수 있지만, 액션, 리듀서, 액션 생성 함수 등 보일러플레이트 코드가 많아지기 쉽습니다.

2) 작은 프로젝트에서는 오히려 비효율적
Redux는 구조화된 상태 관리가 필요한 대규모 애플리케이션에서 빛을 발합니다. 하지만 상태가 간단한 소규모 프로젝트에서는 오히려 복잡성을 증가시킬 수 있습니다.

profile
슬기로운개발생활🤖

0개의 댓글