Redux가 뭐예요

jangws·2022년 5월 14일
1

Redux

목록 보기
1/2
post-thumbnail

Redux란?

  • 리덕스는 cross-component 또는 app-wide 상태를 위한 상태 관리 시스템이다.

상태

  • 상태는 로컬 상태, cross-component 상태, app-wide 상태 와 같이 세 가지로 구분할 수 있다.

Local 상태

  • 로컬 상태는 데이터가 변경되면 하나의 컴포넌트 UI에 영향을 미치는 상태이다. 컴포넌트 내부에서 보통 useState나 useReducer를 사용하여 그런 로컬 상태를 관리한다.
  • ex) 인풋 필드에 사용자의 입력을 감지

Cross-component 상태

  • Cross-component 상태는 다수의 컴포넌트에 영향을 미치는 상태이다. 이를 위해 prop drilling이 발생한다.
  • ex) 모달 창의 개폐 상태

App-Wide 상태

  • App-Wide 상태는 애플리케이션의 모든 컴포넌트에 영향을 미치는 상태이다.이를 위해 prop drilling이 발생한다.
  • ex) 사용자 인증 상태

React Context

  • 이처럼 크로스 컴포넌트나 앱 와이드 상태에서 데이터를 넣고 전체 props 함수를 업데이트하는 건 번거로울 수 있다. 따라서 리액트의 내장 기능인 컨텍스트를 활용하여 이와 같은 상태 관리를 단순화할 수 있다. 컨텍스트를 쓰면 prop drilling을 하지 않을 수 있고, context provider 컴포넌트를 중심으로 상태를 관리할 수 있다.
  • 리덕스도 같은 문제를 해결한다.그런데 리액트 컨텍스트가 이미 있는데 왜 리덕스가 또 필요할까? 리액트 컨텍스트에는 잠재적인 단점이 몇 가지 있기 때문이다.

React Context의 잠재적 단점

Context Hell

  • 리액트 컨텍스트를 사용했을 때, 중소형 앱은 대부분 문제가 일어나지 않으나, 대형 앱을 구축할 경우 다수의 컴포넌트나 전체 앱에 영향을 미치는 상태가 많이 생길 수 있다. 이런 복잡한 상태를 관리하기 위해 ContextPovider 컴포넌트가 아주 많이 만들어지며 심하게 중첩될 수 있다. 이를 Context Hell이라 한다.

성능

  • 컨텍스트는 테마를 변경하거나 인증같은 저빈도 업데이트에는 적합하지만, 데이터가 자주 변경되는 고빈도 업데이트의 경우에는 성능상 좋지 않다고 한다.

리덕스는 컨텍스트의 대안

  • 즉, 단순히 말해서 컨텍스트는 대형 앱이나 고빈도 상태 변경에는 적합하지 않다고 할 수 있다.그리고 리덕스는 이러한 컨텍스트의 잠재적 단점을 해결하기 위한 대안이다.
  • 하지만 컨텍스트나 리덕스 모두 중요하므로 둘 중 하나를 선택하고 나머지를 버려야 하는 것이 아니며, 필요하면 애플리케이션에서 둘 다 사용할 수도 있다.

리덕스의 작동 방식

  • 리덕스는 애플리케이션에 있는 하나의 중앙 데이터(상태) 저장소이다. 정확히 한 개의 저장소만을 가지며, 그 저장소에 크로스 컴포넌트든 앱 와이드 상태든 전체 애플리케이션의 모든 상태를 저장한다.
  • 그러면 관리가 어려울 것 같으나, 다행히 리덕스에서는 그 저장소 전체를 항상 직접 관리할 필요가 없다.
  • 컴포넌트는 중앙저장소에서 구독한 데이터가 변경되면 알림을 받아 필요한 해당 데이터를 받아서 사용한다.
  • 데이터를 변경하는 경우 컴포넌트는 절대로 저장소의 데이터를 직접 조작하지 않는다. 즉, 데이터는 절대로 구독 방향(저장소->컴포넌트)의 반대로 흐르지 않는다.
  • 대신에 리듀서라는 개념을 이용하여 데이터를 변경한다. 이 리듀서 함수는 저장소 데이터의 변경을 담당한다. 다만, 여기서 리듀서라는 용어는 useReducer 훅과는 다르다.
  • 리듀서 함수는 일반적인 개념이다. 리듀서 함수는 입력을 받아서 그 입력을 변환하고 줄임으로써 새로운 결과를 반환하는 함수이다. 예를 들면, 숫자로 된 리스트를 그 숫자들의 합으로 줄일 수 있다.
  • 이러한 리듀서 함수가 저장소 데이터의 업데이트를 담당한다.

컴포넌트와 그 리듀서 함수가 어떻게 연결될까?

  • 예를 들어, 컴포넌트 버튼이 클릭되면, 그것이 데이터 변경을 트리거한다. 트리거는 컴포넌트가 Action을 리듀서 함수에게 Dispatch(발송)하는 것이라 일컬을 수 있다. Action이란, 사실상 단순한 자바스크립트 객체이며, 리듀서가 수행해야 할 작업이 설명되어 있다.
  • 리덕스는 그 Action을 리듀서로 전달한다. 리듀서는 Action이 원하는 걸 수행한 후 새 상태를 반환한다. 리듀서가 반환한 새 상태는 리덕스의 중앙 데이터 저장소의 기존 상태를 대체한다.
  • 그리고 그 과정이 일어나고 데이터 저장소의 상태가 업데이트되면, 이를 구독 중인 컴포넌트는 알림을 받게 되고, 컴포넌트는 UI를 업데이트할 수 있다.

리덕스 코드로 살펴보기

  • 아래 코드는 node와 redux를 설치한 후, node.js로 간단히 실행할 수 있다.

(1) 리듀서 함수

  • 리듀서 함수는 순수 함수이며, 기존의 상태발송된 Action이라는 2개의 매개변수를 받아서 항상 새 상태 객체를 반환한다.
const 초기상태 = {
	counter:  0
}

const 리듀서함수 = (state = 초기상태, action) => {
  if (action.type === 'increment') {
   	return {
    	counter: state.counter + 1
    }
  }
  
  if (action.type === 'decrement') {
   	return {
    	counter: state.counter - 1
    }
  }
  return state;
};

(2) 저장소

const redux = require("redux");
const 저장소 = redux.createStore(리듀서함수);

(3) 구독

const 구독함수 = () => {
 const latestState = 저장소.getState();
  console.log(latestState);
};

저장소.subscribe(구독함수);

// 이 구독함수는 상태가 변경될 때마다 트리거된다.
// getState()는 createStore()로 생성된 저장소에서 사용할 수 있는 메소드이다. 업데이트된 후 최신 상태 스냅샷을 제공한다.

(4) 액션

저장소.dispatch({ type: 'increment' }); // { counter: 1 }
저장소.dispatch({ type: 'decrement' }); // { counter : 0 }

// dispatch()는 액션을 매개변수로 받아 액션을 발송하는 메소드이다.
// 액션은 자바스크립트 객체이다.

0개의 댓글