[React] Redux 알아보기

SungWoo·2024년 9월 29일

React

목록 보기
3/16
post-thumbnail

Redux란?

자바스크립트 애플리케이션에서 상태(state)관리를 효율적으로 하기 위한 라이브러리
(주로 React와 함께 사용되지만, 다른 자바스크립트 프레임워크나 라이브러리와도 함께 사용 가능)

우리가 state(상태), 즉 어플리케이션을 변경하고 화면에 표시하는 데이터를 관리하도록 도와줌
(ex. 사용자가 버튼을 클릭하면 그 데이터가 변경되는 등...)

Redux의 핵심 개념 4가지

1. 중앙 집중식 상태 관리

Redux는 애플리케이션의 모든 state를 중앙에서 관리합니다. 이 중앙 상태 저장소(store)를 통해 애플리케이션의 다양한 컴포넌트가 state를 쉽게 공유하고 관리할 수 있도록 도와줍니다. 이를 통해 state가 여러 컴포넌트에 흩어져 있을 때 발생하는 문제를 줄일 수 있다는 장점이 있습니다.

2. 일관된 데이터 흐름

Redux는 단방향 데이터 흐름(unidirectional data flow)을 사용합니다. 즉, 상태를 변경하려면 action이라는 객체를 만들어야 하고, 이 actionreducer라는 함수를 통해 처리됩니다. reducer는 현재 stateaction을 받아서 새로운 state를 반환합니다. 이를 통해 상태 변경이 예측 가능하고, 디버깅이 쉬워진다는 장점이 있습니다.

3. 불변성(immutabillity)

Redux에서는 state가 변경될 때 기존 state를 직접 수정하지 않고, 새로운 state 객체를 반환합니다. 이를 통해 state의 변화를 추적하기 쉽고, 애플리케이션의 버그를 줄일 수 있습니다.

4. 미들웨어(middleware)

Redux는 미들웨어를 사용하여 action을 처리하는 과정을 확장할 수 있습니다. 예를 들어 비동기 작업(예: API 호출)을 처리할 때 미들웨어를 사용해 actiondispatch할 수 있습니다. 대표적인 미들웨어로는 redux-thunkredux-saga가 있습니다.


1. State(상태)의 종류

1) Local State

: state가 하나의 컴포넌트에 종속되어 영향을 미치는 상태

  • useState(), useReducer() 등을 통해 관리함

ex. User input, Toggle button

2) Cross-Component State

: 다수의 컴포넌트에 영향을 미치는 state(상태)

  • prop chain을 구축하거나 prop drilling을 통해 state를 전달해주어야 함

ex. Modal overlay

3) App-Wide State

: state가 앱 전역에 영향을 미치는 상태

  • prop chain을 구축하거나 prop drilling을 통해 state를 전달해주어야 함
    해결책: React Context 사용

ex. User authentication(사용자 인즏 = 로그인)


Q. 다수의 컴포넌트에 영향을 미치는 상태를 관리하는 리액트 컨텍스트가 이미 있는데 리덕스가 필요한가?

: 리덕스는 유동적인 상태 확산이 가능하지만 리액트 컨텍스트는 그렇지 않다.

2. 리액트 컨텍스트의 잠재적인 단점

1) 복잡한 설정 및 관리

  • 리액트 컨텍스트를 사용하면 설정 및 상태 관리가 상당히 복잡해 질 수 있음(구축하는 어플리케이션의 종류에 따라 다름)
  • 하나의 컨텍스트에서 많은 것들을 관리하게 될 경우 유지 관리가 어려울 수 있음
  • 다수의 컨텍스트로 나누게 되면 아래 코드와 같은 모습이 나옴
// ex. 대형 어플리케이션
return (
	<AuthContextProvider>
    	<ThemeContextProvider>
        	<UIInteractionContextProvider>
            	<MultiStepFormContextProvider>
                	<UserRegistration />
                </MultiStepFormContextProvider>
            </UIInteractionContextProvider>
        </ThemeContextProvider>
    </AuthContextProvider>
)

2) 성능

: 2018년 당시 도입된 이 컨텍스트는 테마를 변경하거나 인증 같은 저빈도 업데이트에는 아주 좋지만, 데이터가 자주 변경되는 경우에는 좋지 않으며, 유동적인 상태 확산을 대체할 수 없다는 리액트 팀원의 언급이 있었음.

"리액트 컨텍스트는 모든 시나리오와 모든 경우에서 리덕스를 대체할 수 없다."


3. Redux의 작동 방식

: 리덕스는 애플리케이션에 존재하는 하나의 중앙 데이터 저장소(전체 애플리케이션의 모든 상태를 저장)

  • Reducer 함수가 저장소 데이터의 업데이트를 담당
  • 그리고 저장소의 데이터를 Subscribe하는 컴포넌트가 존재

[순서]
1) 컴포넌트가 Action을 발송(dispatch)
2) Redux는 그 Action을 Reducer로 전달하고 원하는 작업에 대한 설명을 읽게 됨
3) Reducer가 그 작업을 수행
4) Reducer가 새로운 상태를 뱉어내면 중앙 데이터 저장소에 있던 기존 데이터를 대체
5) 데이터 저장소의 상태가 업데이트 되면 구독중인 컴포넌트가 알림을 받게 되고 컴포넌트는 UI를 업데이트 할 수 있게 됨


4. Reducer 함수

  • Reducer(Old State, Dispatched Action)
    => Output: New State Object

  • 리듀서 함수는 Side Effect를 발생시키지 않는 순수 함수가 되어야 함
    ↪ 동일한 입력값에는 동일한 결과값이 나와야 함
    ↪ http 요청 등의 효과는 일어나지 않아야 함

// [Setting - Vanilla Javascript]
const redux = require('redux')

// 1. Reducer
const counterReducer = (state = { counter: 0 }, action) => {
	if (action.type === 'increment') {
        return {
            counter: state.counter + 1,
        };	
    }
    if (action.type === 'decrement') {
    	return {
        	counter: state.counter - 1,
        };
    };
    
    return state;
};

// 2. Store
const store = redux.createStore(counterReducer);

// 3. Subscriber
const counterSubscriber = () => {
	const latestState = store.getState();
};

// Subscribe 지정
store.subscribe(counterSubscriber);

// [Action 발송]
store.dispatch({ type: 'increment' })
store.dispatch({ type: 'decrement' })

// [Result]: { counter: 1 } → { counter: 0 }

비고

※ Reducer 함수는 반드시 "순수 함수"이어야 한다

: 어떠한 side-effect(부수 효과)도 발생시키지 않고, 동기식이어야 한다.

  • input을 받아 output을 생성해 내는 순수하고 부수효과가 없으며, 동기식 함수
  • 같은 input과 같은 값일 경우 항상 동일한 output을 생성하며 이를 차단하는 비동기 코드도 없고 도중에 발생하는 부수 효과도 없는 함수

Q. 그렇다면 리덕스로 작업할 때 보내야 하는 HTTP 요청과 같이 부수 효과가 수반되는 일부 작업을 전달할 이 코드는 어디에 넣어야 하는가?

1) 컴포넌트 안에 useEffect()를 사용하여 부수 효과가 발생하는 코드를 작성 → 해당 부수 효과가 완료된 후에만 작업을 전달

2) 자신만의 새로운 Action creater 함수를 생성 → 자동으로 생성된 리덕스 툴킷이 제공하는 것을 사용하지 않을 수 있음

↪ 리덕스는 해당 부수 효과에 대해 아무것도 알지 못함


※ redux-thunk란?

: 특정 작업을 나중에 하도록 미루기 위해 함수 형태로 감싼 것

  • 리덕스 미들웨어
  • 위 미들웨어는 객체 대신 함수를 생성하는 액션 생성함수를 작성할 수 있도록 도와줌

1) 일반 액션 생성자
: 매개변수를 받아서 액션 객체를 생성하는 작업을 담당
↪ 만약 특정 액션이 몇초뒤에 실행하게 하거나, 현재 상태에 따라 무시되게 하는 것은 불가능

2) redux-thunk
: 조건에 따라 액션을 dispatch 하거나 무시할 수 있음

보통의 액션 생성자는 하나의 액션 객체를 생성할 뿐이지만 redux-thunk를 통해 만들게 되면 그 내부에서 여러가지 작업을 할 수 있기에 활용도가 높아짐

profile
어제보다 더 나은

0개의 댓글