말하는 컴공감자의 텃밭

React - Redux 본문

프론트엔드/React

React - Redux

현콩 2024. 2. 7. 18:53
728x90

Redux ?

JavaScript 앱에서 상태 관리를 위한 자바스크립트 라이브러리이다.

UI 라이브러리/프레임워크와 함께 사용될 때 매우 유용하며, 애플리케이션의 상태(state)를 예측 가능한 방식으로 관리할 수 있다.

여기서 "상태"란 앱에서 관리해야 하는 모든 데이터를 말한다.

 

 

자바 스크립트는 PropsState로 컴포넌트 안에서 데이터를 교환하고, 통신하는 두 용어를 정리해보자.

  • Props (속성):  부모 컴포넌트로부터 자식 컴포넌트에게 전달되는 데이터이다.
    • Props는 컴포넌트가 받는 입력과 같으며, 컴포넌트 내에서 변경할 수 없다.
    • 컴포넌트를 재사용하고 구성할 수 있는 방식이다.
    • 값을 변경하고자해도 자식에서 변경은 불가능하며 부모의 내부를 변경해야 한다.
  • State (상태):  컴포넌트가 관리하는 데이터로, 컴포넌트의 상태를 변경할 수 있다.
    • 사용자의 상호작용이나 시간의 경과에 따라 변경될 수 있는 데이터를 관리할때 용이하다.
    • 결국 컴포넌트 안에서 데이터를 전달하는데 사용되고 State가 변하면 re-render 된다.

 

Redux는 State를 관리하는 라이브러리인데. 예시를보며 이해해보자.

 

하단의 보라부분의 상태가 변경된경우 인근 노드들이 모두 수정되어야하는 불편함이 존재했다.

다만 Redux는 Store에 저장하여 사용한다.

앱의 상태 관리를 중앙에서 처리하기에 컴포넌트 간의 상태 공유와 상태 업데이트 로직의 복잡성을 줄여 준다.

 

Redux는 3가지 원칙이 존재하는데

  1. 애플리케이션 상태는 중앙에서 집중 관리한다.
  2. 상태는 불변(읽기 전용) 데이터 이며, 오직 액션 만이 상태를 교체를 바꿀 수 있다.
    1. 이로써 예측이 가능하다.
  3. 리듀서(함수)를 통해 상태의 최종 값만 설정한다.

리덕스의 메서드

 

Store 스토어

Redux 스토어(Store)는 Redux에서 애플리케이션의 상태(state)를 저장하는 장소이다.

스토어는 Redux 애플리케이션의 핵심으로, 애플리케이션의 전체 상태 트리를 포함한다.

 

Action 액션

액션은 상태를 변경하는 유일한 방법이다.

액션은 타입(type) 속성을 가진 일반 JavaScript 객체이다.

액션은 애플리케이션에서 어떤 일이 발생했는지를 설명하고, 이 정보를 스토어에 전달한다.

 

Reducer 리듀서

리듀서는 액션을 처리하고 상태의 다음 상태를 반환하는 함수이다.

리듀서 함수는 (previousState, action) => newState 형태를 띈다.

액션을 받아 현재 상태와 함께 처리하고, 새 상태를 반환한다.

리듀서는 부수 효과를 일으키지 않고, 주어진 인수를 변경하지 않으며, 동일한 인수에 대해 항상 동일한 결과를 반환해야한다.

 

Subscription 구독

구독 메커니즘을 통해, 스토어의 상태가 변경될 때마다 리스너 함수가 호출된다.

이를 통해 상태 변경에 따라 UI를 업데이트할 수 있다.

subscribe(listener) 메서드를 사용하여 스토어에 리스너를 등록한다.

 

View 뷰 / Component 컴포넌트

뷰(또는 컴포넌트)는 사용자 인터페이스를 구성하는 요소다.

컴포넌트 기반 개발을 통해 UI를 구성합니다.

컴포넌트는 Redux 스토어의 상태를 props로 받아와서 사용할 수 있습니다.

컴포넌트는 dispatch 메서드를 사용하여 액션을 스토어에 발송할 수 있으며, 이를 통해 상태를 업데이트한다..

 

 예시 

간단한 카운터 애플리케이션을 만들어 개념을 확인해보자.

먼저 Strore를 생성해주었다. createStrore 메서드를 활용해준다. 인자는 리듀서가 되겠다.

import { createStore } from 'redux';

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

const store = createStore(counterReducer);

가능한 액션은 숫자 증가와 감소 두가지로 정해져있다.

 

스토어의 현재 상태는 getState 메서드를 사용하여 접근할 수 있다.

console.log(store.getState()); // 0

 

액션은 dispatch 메서드를 사용하여 전송된다. 액션은 최소한 type 속성을 가져야 한다..

 

store.dispatch({ type: 'INCREMENT' });
console.log(store.getState()); // 1

store.dispatch({ type: 'DECREMENT' });
console.log(store.getState()); // 0

 

리듀서는 액션을 처리하고 새로운 상태를 반환하는 함수이다. 여러 상태 업데이트 로직을 포함한다.

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

 

subscribe 메서드를 사용하여 상태 변경을 구독하고, 상태가 변경될 때마다 콜백 함수를 실행할 수 있다.

const unsubscribe = store.subscribe(() => console.log('Current state:', store.getState()));

// 상태 변경을 구독 취소하려면 unsubscribe를 호출합니다.
// unsubscribe();

 

React 컴포넌트에서 Redux 스토어의 상태를 사용하고, 액션을 발송하는 예시다.

 react-redux useSelector useDispatch 사용한다.

import React from 'react';
import { useSelector, useDispatch } from 'react-redux';

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

  return (
    <div>
      <span>{count}</span>
      <button onClick={() => dispatch({ type: 'INCREMENT' })}>Increment</button>
      <button onClick={() => dispatch({ type: 'DECREMENT' })}>Decrement</button>
    </div>
  );
}

 

시나리오 

  1. 사용자가 "Increment" 버튼을 누른다.
  2. dispatch({ type: 'INCREMENT' }) 함수가 호출되어 'INCREMENT' 액션을 스토어로 전송한다.
  3. 스토어는 리듀서 함수에 현재 상태와 발송된 액션을 전달한다.
  4. 리듀서는 액션 타입에 따라 새로운 상태를 계산하고 반환한다. 이 경우, 카운터 값이 1 증가한다.
  5. 스토어의 상태가 업데이트되고, useSelector를 사용하여 상태를 구독하는 컴포넌트는 자동으로 리렌더링된다. 새로운 카운터 값이 화면에 표시된다.

리덕스 동작과정 gif

 

액션을 통해 상태 변화를 요청하면 리듀서에서는 그 액션에 따라 새로운 상태를 반환하여 애플리케이션의 상태를 업데이트한다. React 컴포넌트는 이 상태를 사용하여 UI를 렌더링하고, 사용자 인터페이스는 항상 현재 상태를 반영한다.

 

728x90

'프론트엔드 > React' 카테고리의 다른 글

React - TDD, Testing Library, Jest, expect, matcher  (1) 2024.02.06
React - Memoization  (0) 2024.02.02
React - 불변성 정리  (1) 2024.02.01
React - State, Props, 구조분해할당  (0) 2024.01.31
Comments