[React] react + redux

Gyuhan Park·2023년 1월 25일
0

react

목록 보기
4/11

Redux 등장배경

Redux 이전에는 MVC(Model View Controller)패턴 이 유행이였다.
하지만, Facebook에서 기존의 MVC 아키텍처는 양방향 데이터 흐름을 가지고 있기 때문에 프로그램이 커질수록 복잡성이 기하급수적으로 증가하는 문제를 알게 되었다.
Model이 변경되면 View가 변경되며, 유저에 의해 View에서 Action이 일어난다면 Model은 View에서 변경된 데이터를 처리해야하는 양방향 데이터 흐름을 가진다.

이 때문에 Flux라는 디자인패턴이 나오게 되었다. Flux는 단방향 데이터 흐름을 가지고 있으며, action, dispatcher, store, view 를 갖는다.

action -> dispatcher -> store -> view

action이 발생하면 dispatcher에 의해 store에 변경된 데이터를 저장하고, 변경된 데이터에 따라 view가 변경되는 단방향 데이터 흐름

이 flux 패턴에 reducer 개념을 도입해 개선한 아키텍처 -> Redux
dispatcher 대신 reducer가 상태변화로직을 담당하였다.

Flux와 Redux

디렉토리 구조

일반적인 구조 : actions, constants, reducers라는 3개의 디렉토리를 만들고 그 안에 기능별로 파일을 하나씩 만드는 방식. redux 공식 홈페이지에서 보여주는 구조.
Ducks 패턴 : 액션 타입, 액션 생성 함수, 리듀서 함수를 파일 하나에 몰아서 modules 디렉토리 안에 기능별로 작성하는 방식.

todo-list로 만든 react 프로젝트에 디렉토리 구조를 redux에 맞게 수정하였다.
상태관리가 이루어지지 않고 UI만 보여주는 컴포넌트인 프레젠테이셔널 컴포넌트와 리덕스와 연동되는 컨테이너 컴포넌트도 분리하였다.

리덕스 용어 개념

난 용어 정리가 안되서 진짜 골때렸다. 그래서 각각 뭐하는 애들인데?? 내가 이해한대로 redux 용어 개념에 대해 정리해보았다.

action

state가 변하는 이벤트 : action.
자바스크립트 순수 객체로 정의된다.
액션을 다룰 때 액션 타입 정의와 액션 생성 함수로 나눌 수 있다.

액션 타입 : 액션의 이름. reducer의 switch case로 쓰임.
액션 생성 함수 : 액션 타입에 따라 적절한 액션을 반환하는 함수.

어떤 사건이 발생하여 state값 변경이 필요하면 action을 발생시킨 후,
액션 객체를 dispatch() 함수의 인자로 넘겨주면 reducer 함수가 실행된다.

// 액션 타입 정의
const INCREASE = 'todo/INCREASE';
// 액션 생성 함수
export const increase = () => ({ type: DECREASE });

// 액션 객체 예시
{ type: 'ADD_TODO', text: 'Go to swimming pool' }
{ type: 'TOGGLE_TODO', index: 1 }
{ type: 'SET_VISIBILITY_FILTER', filter: 'SHOW_ALL' }

reducer

(prevState, action) => newState

액션을 만들어서 발생시키면 리듀서가 현재상태와 액션객체를 받아옴. 두 값을 가지고 새로운 상태를 만들어 반환.
리듀서 함수가 상태를 업데이트하여 스토어의 값이 바뀌면 새로운 props를 내려주면서 컴포넌트가 리렌더링된다.

reducer(prevState, action) // newState 반환

초기 state값을 default값으로 설정할 수 있고 action.type에 따라 다른 상태변화를 일으킨다.

store

상태가 보관되는 하나의 저장소.
어플리케이션의 모든 상태는 하나의 스토어에서 관리된다. 스토어 안에는 현재의 앱 상태와 리듀서, 추가적인 내장 함수들이 들어있다.

dispatch

액션을 발생시키는 것.
스토어의 내장 함수.

dispatch(action 생성함수)

dispatch()가 호출되면 스토어는 리듀서 함수를 실행시켜 새로운 상태 반환.

subscribe

액션이 디스패치되어 상태가 업데이트될 때마다 함수 호출

store.subscribe(listener);

react-redux 라이브러리에서 제공하는 connect() 또는 useSelector 을 사용하여 리덕스 스토어의 상태에 따라 리렌더링 되므로 잘 사용되지 않는다.

리덕스 흐름

  1. 각각의 액션 및 액션 생성함수를 정의한다.
  2. 각각의 서브 리듀서를 정의한다.
  3. 서브 리듀서들을 하나의 루트 리듀서로 병합한다.
  4. 루트 리듀서를 등록한 스토어를 생성한다.
  5. 컴포넌트와 스토어를 연동시켜 뷰에서 상태값을 사용할 때 스토어에 연결하여 사용한다.

각각의 액션 및 액션 생성함수 정의

액션 타입을 정의하고 액션 생성 함수를 export 한다.

const INCREASE = 'todo/INCREASE';
export const increase = () => ({ type: INCREASE });

각각의 서브 리듀서 정의

function todo(state = initialState, action) {
  switch (action.type) {
  	...
    case INCREASE: {
      const newTodos = state.todos.slice().sort(function (a, b) {
        if (a.text > b.text) return 1;
        if (a.text < b.text) return -1;
        return 0;
      });
      return { todos: newTodos };
    }
	...
    default:
      return state;
  }
}
export default todo;

루트 리듀서로 병합

리듀서를 여러개 만든 경우 스토어에 넣기 위해 리듀서를 하나로 합쳐야 한다.

import { combineReducers } from 'redux';
const rootReducer = combineReducers({
counter,
todos,
});
export default rootReducer;

루트 리듀서를 등록한 스토어 생성

생성한 스토어를 리액트 컴포넌트에서 사용할 수 있도록 Provider로 App을 감싸준다.

...
import rootReducer from './modules';
import { Provider } from ' react-redux';

const store = createStore(rootReducer);
...
root.render(
  <Provider store={store}>
  	<App />
  </Provider>
)

컴포넌트와 스토어 연동

컴포넌트와 스토어를 연동하기 위해 react-redux의 connect() 사용

connect(mapStateToProps, mapDispatchToProps)(컴포넌트)

mapStateToProps : 스토어 안의 상태를 컴포넌트의 props로 넘겨주는 함수
mapDispatchToProps: 액션생성함수를 props로 넘겨주는 함수

import { connect } from "react-redux";
import { increase } from "../../actions/todo";

const Todo = ({ [props이름], increase }) => {
  return (
    <TodoList
      todos={props이름}
      onIncrease={increase}
    />
  );
};

const mapStateToProps = (state) => ({
  [props이름]: state.[리듀서이름].todos,
});

const mapDispatchToProps = (dispatch) => ({
  increase: () => {
    dispatch(increase());
  },
});

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

적용 결과

다행히 오류 안남 ㅎㅎㅎㅎㅎ (사실 하루종일 삽질해서 겨우 살짝 이해한 정도?)

[React] 리덕스 (Redux) 이해하기
Flux와 Redux에 대한 이해
Redux 공식문서
[리액트를 다루는 기술 개정판]

profile
단단한 프론트엔드 개발자가 되고 싶은

0개의 댓글