본문 바로가기

Computer Programming/React

Redux(리덕스) 사용 이유 (Context와 차이점)와 작동방식

1. Redux란?

리덕스는 cross-component 또는 app-wide 상태를 위한 상태 관리 시스템이다. 즉, 다수의 컴포넌트 또는 앱 전체에서 상태 변경을 관리하도록 도와주는 시스템이다.

 

 

2. State의 세가지 정의

1) local state

: 하나의 컴포넌트 내에서 데이터가 변경되어 해당 컴포넌트에 속하는 UI에 영향을 미치는 state이다. 주로 useState을 이용해 state 변수에 저장한다.

 

예를 들면, input field를 켜고 끄는 “show more” 토글 버튼이 있다. 컴포넌트가 약간 복잡하다면 useState을 사용할 수도 있지만 useReducer을 많이 사용한다.

 

2) cross-component state

: 두개 이상의 컴포넌트에 영향을 미치는 state이다. 즉 props chains 혹은 prop drilling 을 활용해 state를 부모자식간에 넘겨주는 관계일 경우이다.

 

예를 들면, 모달 컴포넌트가 있고 해당 모달 컴포넌트가 다수의 컴포넌트에 상태를 전달하는 영향을 미칠 경우이다. 이 때 모달을 열고 닫는 토글 버튼도 해당 될 수 있다. 이 모달 기능을 위해 다수의 컴포넌트가 협력하며 props 체인을 구축한다.

 

3) App-wide state

: 다수의 컴포넌트 뿐만 아니라 대부분의 컴포넌트 혹은 앱 전체에 state가 영향을 미치는 경우에 해당된다.

 

예를 들면, user authentication status 등이 있다. App-Wide state 또한 prop chains, prop drilling 을 구축해야한다.

 

 

Redux 또한 React의 내장 기능인 Context API와 같이 Cross component state 나 app-wide state 을 관리하도록 도와주는 역할을 한다.

 


 

3. Redux vs Context API

리액트 컨텍스트를 쓰면 context 와 contextProvider 컴포넌트를 중심으로 props chain이나 prop drilling을 방지할 수 있다. 그럼에도 Redux를 따로 사용해야 하는 이유는 무엇일까?

 

 

4. Context의 잠재적 단점

1) 셋업 과정과 상태 관리의 복잡성

앱의 종류에 따라 복잡성이 달라질 수 있지만, 많은 수의 컴포넌트와 내용이 있는 대형 프로젝트의 경우 위 코드처럼 컨텍스트를 과도하게 사용해야하는 경우가 나타날 수 있다.

 

따라서 위의 사진과 같은 많은 ContextProvider 컴포넌트를 사용하게되고 이는 코드를 복잡하게 만든다.

 

만약 이를 방지하기 위해 하나의 Provider 만 만든다면, 그 컴포넌트 하나가 다양한 많은 state를 관리하게 되고 이는 유지보수를 어렵게 만든다.

 

 

2) 성능

앱의 테마를 변경하거나 authentication과 같은 저빈도 업데이트에는 성능에 문제가 없지만, 데이터가 자주 변경되는 경우에는 성능 저하의 잠재적 문제가 있다.

 

 

 

따라서 리액트 컨텍스트가 Redux를 완벽하게 대체하기는 어렵다고 본다.

 

 

5. Redux 작동 방식

리덕스를 사용하면 앱에서 단 하나의 중앙 데이터 장소를 갖게 된다. (Central Data Store)

=> 해당 저장소에는 앱의 모든 데이터 상태를 저장한다.

*Store: A store holds the whole state tree of your application. The only way to change the state inside it is to dispatch an action on it.

https://redux.js.org/api/store#:~:text=In Redux%2C subscriptions are called,must have no side effects.

 

 

이를 통해 다른 컴포넌트에서 데이터 저장소에 접근하고 앱의 모든 상태를 관리할 수 있게 된다.

 

예를 들어 사용자의 인증 상태가 변경되면 컴포넌트에서 그러한 상황을 인지하고, 그에 맞춰 UI를 업데이트한다. 이를 위해 component는 store에 subscription을 설정하고, 이후 컴포넌트는 인증상태와 같은 현재 필요한 저장소의 일부 데이터를 받게 되는 것이 해당된다.

 

 

그러나 컴포넌트는 store 의 데이터를 직접 조작하지는 않는다. subscription을 통해 데이터에 접근할 수만 있다. 따라서 개발자들은 store의 데이터 state를 변경하고 싶다면 Reducer Function 이라는 개념을 사용해야한다.

 

Reducer은 리액트 hooks 의 하나인 useReducer과는 다르다. Reducer 이라는 개념은 입력을 변환하고, 새로운 출력을 뱉어내는 일반적인 프로그래밍 개념이다.

출처: InterviewBit

 

 

컴포넌트 내에서 이벤트가 발생해 데이터의 변경을 필요로 한다면, 즉 trigger 가 발생한다면

컴포넌트에서는 Action을 Dispatch한다.

Action이란 단순한 자바스크립트 객체이고 이는 리듀서가 수행해야할 작업을 설명하는 역할을 한다.

리덕스는 해당 Action을 Reducer로 전달하고 Reducer는 작업을 수행하며 데이터의 상태를 변경한다.

그 후 store 에 저장되어 있던 기존 상태를 새로운 상태로 변경한다.

 

=> 새로운 상태로 변경되면 Action을 보냈던 component가 알림을 받게 되고, 컴포넌트는 UI를 변경할 수 있게 된다.

 

 

Component → Dispatch Actions → Reducer Received → do actions → Reducer generates new State → notify component → Component changes UI

 

 

6. Redux 설치

# NPM
npm install redux

# Yarn
yarn add redux