프론트/front-end

[Redux] 리덕스란? - 리덕스 개념 및 사용방법

연지양갱 2024. 1. 21. 19:00
728x90
반응형
SMALL

이번에 프로젝트를 진행하면서 리덕스를 사용해보라고 하더라구요!

근데 사용해본 경험이 없어서 이번에 정리하면서 알아보고 제대로 사용해보려고 합니다.

리덕스의 개념과 사용하는 이유, 사용 방법에 대해 알아보겠습니다

 

먼저..!

리덕스를 사용하기 전에 리덕스 문서를 한번 살펴봐야겠죠?

저는 사용할 때 문서를 한번이라도 꼭 읽어보는게 좋다고 생각해요

https://ko.redux.js.org/

 

Redux - 자바스크립트 앱을 위한 예측 가능한 상태 컨테이너. | Redux

자바스크립트 앱을 위한 예측 가능한 상태 컨테이너.

ko.redux.js.org

 

Redux란?

리덕스는 자바스크립트 앱을 위한 예측 가능한 상태 컨테이너입니다.

리덕스는 앱을 만들면서 상태관리할 수 있는 거라고 이야기를 들은적이 있어요.

앱의 상태 전부를 하나의 저장소(store)안에 있는 객체 트리에 저장됩니다. 

상태 트리를 변경할 수 있는 방법은 서술하는 객체인 액션(action)을 보내는 것 뿐입니다. 액션이 상태 트리를 어떻게 변경할 지 명시하기 위해 리듀서를 작성해야합니다.

리액트(React)에서 사용할 수 있는 useState를 사용할 경우에는 컴포넌트 안에 useState를 만들어서 props로 전달해주는 방식이었답니다..

하지만! 리덕스를 사용하면 컴포넌트에 종속되지 않고 상태관리를 컴포넌트 외에서 할 수 있습니다.

즉,  Redux가 제공해주는 것은 애플리케이션의 여러부분에 필요한 상태인 전역 상태를 관리하는 데 도움됩니다.

Redux에 제공하는 패턴과 도구를 사용하면 애플리케이션의 상태가 언제, 어디서, 왜 어떻게 업데이트되고 이러한 변경이 발생할 때 애플리케이션 로직이 어떻게 작동하는지 더 쉽게 이해할 수 있습니다.

 

 

그렇다면

언제 Redux를 사용해야 할까요?

리덕스는 공유 상태 관리를 처리하는 데 도움이 되지만 다른 도구와 마찬가지로 장단점이 있습니다.

- 앱의 여러 위치에 필요한 많은 양의 애플리케이션 상태가 있습니다.

 - 앱 상태는 시간이 지남에 따라 자주 업데이트 됩니다.

 - 해당 상태를 업데이트하는 논리는 복잡할 수 있습니다.

 - 앱에 중간 또는 대규모 코드 베이스가 있으며 많은 사람들이 작업할 수 있습니다.

 

클릭과 같은 사용자 상호작용에 대한 응답으로 작업이 전달됩니다.

저장소는 새로운 상태를 계산하기 위해 감속기 기능을 실행합니다.

UI는 새 상태를 읽어 새값을 표시합니다.

Reducer(리듀서)는?

내부의 모든 종류의 로직을 사용하여 새로운 상태가 무엇인지 결정할 수 있습니다.

코드를 한번 보시죠.

const actions = [
  { type: 'counter/incremented' },
  { type: 'counter/incremented' },
  { type: 'counter/incremented' }
]

const initialState = { value: 0 }

const finalResult = actions.reduce(counterReducer, initialState)
console.log(finalResult)
// {value: 3}

액션 배열을 생성하고 reduce()를 하여 리듀서 함수를 전달하면 동일한 방식으로 최종 결과를 얻을 수 있습니다.

상태가 업데이트 되는 방식을 지정하려면 리듀서 함수를 작성해야 합니다.

 

 

Redux의 장단점

앞서 말씀 드린것 처럼 애플리케이션의 상태를 중앙 집중화하여 예측 가능하고 효율적으로 관리할 수 있습니다. 

장점

1. 예측 가능한 상태관리 :Redux는 단방향 데이터 흐름을 따르기 때문에 상태 변화를 예측할 수 있습니다. 상태 변경은 액션을 통해 이루어지며, 순수한 함수인 리듀서를 통해 관리됩니다. 이로써 상태 변화를 추적하고 디버깅하기가 용이합니다.

2. 중앙 집중화된 상태 : Redux는 단일 스토어를 사용하여 애플리케이션의 전역 상태를 관리합니다. 이는 여러 컴포넌트 간에 상태를 공유하고 데이터를 동기화하는 데 도움이 됩니다.

3. 개발자 도구지원 : Redux는 개발자 도구를 제공하여 상태변화를 모니터링하고 디버깅할 수 있습니다. 액션과 상태의 히스토리를 살펴보거나 시간 여행(debugging in time)을 통해 이전상태로 돌아갈 수 있습니다.

 

단점

1. 복잡성: Redux는 상태 관리를 위한 추가적인 레이어를 도입하기 때문에 간단한 애플리케이션에서는 과도한 복잡성일 수 있습니다. 작은 규모의 프로젝트에서는 상태 관리를 위해 Redux를 도입하는 것이 비효율적일 수 있습니다.

2. 보일러플레이트 코드: Redux를 사용하면 액션, 리듀서, 스토어 등을 정의해야 합니다. 이에 따라 추가적인 코드 작성이 필요하며, 초기 설정 시 보일러플레이트 코드가 늘어날 수 있습니다.

이런 장단점이 있습니다.. 

그렇기 때문에 필요한 경우와 불필요한 경우를 구분해서 사용 여부를 파악하는 것이 좋겠죠?

 

 

 

Redux 함수

Redux는 현재 애플리케이션의 상태는 store이라는 객체에 있습니다.

저장소는 리듀서를 전달하여 생성되며 getState현재 상태값을 반환하는 메소드가 있습니다.

import { configureStore } from '@reduxjs/toolkit'

const store = configureStore({ reducer: counterReducer })

console.log(store.getState())
// {value: 0}

 

Redux 저장소에는 dispatch. 상태를 업데이트하는 유일한 방법은 store.dispatch() 액션 객체를 호출하여 전달하는 것입니다.

저장소는 리듀서 함수를 실행하고 새 상태 값을 내부에 저장하며, getState()업데이트된 값을 검색하기 위해 호출할 수 있습니다.

store.dispatch({ type: 'counter/incremented' })

console.log(store.getState())
// {value: 1}

Selectors는 저장소 상태 값에서 특정 정보를 추출하는 방법을 아는 함수입니다.

애플리케이션이 커짐에 따라 앱의 여러부분이 동일한 데이터를 읽어야 하기 때문에 논리 반복을 방지하는데 도움이 될 수 있습니다.

const selectCounterValue = state => state.value

const currentValue = selectCounterValue(store.getState())
console.log(currentValue)
// 2

 

 

 

 

이렇게 문서에 작성되어 있는 내용입니다..

사실 이렇게 읽어보고 이해하려고 했지만, 저는 직접 실습을 해야지 더 빨리 이해할 수 있더라구요

바로 예제를 보면서 실습으로 들어가보겠습니다.

 

 

Redux 사용하기 - 실습

1. redux를 먼저 설치해줍니다.

# NPM
npm install redux
npm install react-redux

# Yarn
yarn add redux react-redux

 

2. RootReduxer 정의

여러 reducer을 사용하는 경우 reducer을 하나로 묶어주는 메소드

reducers/index.js

import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { createStore } from 'redux';
import rootReducer from './reducers';
import App from './App';

const store = createStore(rootReducer);

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

action.js파일

// 액션 타입 정의
export const INCREMENT = 'INCREMENT';
export const DECREMENT = 'DECREMENT';

// 액션 생성자 함수
export const increment = () => {
  return { type: INCREMENT };
};

export const decrement = () => {
  return { type: DECREMENT };
};

reducers.js 파일

import { INCREMENT, DECREMENT } from './actions';

// 초기 상태 정의
const initialState = {
  count: 0,
};

// 리듀서 함수
const rootReducer = (state = initialState, action) => {
  switch (action.type) {
    case INCREMENT:
      return {
        ...state,
        count: state.count + 1,
      };
    case DECREMENT:
      return {
        ...state,
        count: state.count - 1,
      };
    default:
      return state;
  }
};

export default rootReducer;

App.js 

import React from 'react';
import { connect } from 'react-redux';
import { increment, decrement } from './actions';

const App = ({ count, increment, decrement }) => {
  return (
    <div>
      <h1>Count: {count}</h1>
      <button onClick={increment}>Increment</button>
      <button onClick={decrement}>Decrement</button>
    </div>
  );
};

const mapStateToProps = (state) => {
  return {
    count: state.count,
  };
};

const mapDispatchToProps = {
  increment,
  decrement,
};

export default connect(mapStateToProps, mapDispatchToProps)(App);

 

index.js 파일에서는 스토어를 생성하고, rootReducer를 전달하여 애플리케이션에 Redux를 적용합니다.

actions.js파일에서는 액션 타입을 정의하고, 액션 생성자 함수를 작성합니다.

reduxers.js 파일에서는 초기 상태와 리듀서 함수를 정의합니다.

App.js 파일에서는 리덕스 상태를 컴포넌트에 매핑하고 액션을 디스패치 할 수 있는 컴포넌트를 작성합니다.

redux를 활용하여 상태를 관리하고, 컴포넌트 간에 데이터를 전달할 수 있습니다.

 

오늘은 리덕스에 대해서 알아봤는데요.

일단은 진짜 실전에 사용을 해봐야지 장단점을 몸소 알 수 있을 거 같네요..

리덕스를 사용해보고 다시 수정하도록 하겠습니다..

일단은 오늘은 리덕스 예제 코드를 분석해봐야겠네요..! 

 

써보신 분들이 계신다면 댓글 달아주세요..!

그리고 꼭 알아야하는 부분이나 틀린부분이 있다면 꼭꼭꼭 알려주세요!

 

 

 

 

참고

https://ko.redux.js.org/tutorials/essentials/part-1-overview-concepts

https://medium.com/@heoh06/%EB%A6%AC%EC%95%A1%ED%8A%B8-redux%EC%99%80-%EC%82%AC%EC%9A%A9%EB%B2%95-731853fc3cd4

 

 

 

 

반응형