[TIL] Redux

ㅜㅜ·2022년 11월 2일
1

Today I learn

목록 보기
45/77
post-thumbnail

Redux

전역 상태를 관리할 수 있는 저장소인 Store를 제공함으로써 상태 관리에 도움을 줌.

(🤪 _Redux는 flux 패턴을 구현한 라이브러리인데 react 외에서도 사용할 수 있다. 원리가 flux 패턴과 비슷하므로 아래쪽에선 flux에 대해서도 살펴본다. redux에서는 flux 패턴에서 언급한 dispatch에 등록된 callback 함수를 reducer라고 부르는듯?)

Redux의 작동 방식

: 상태 변경 이벤트 발생시, 변경될 상태에 대한 정보가 담긴 Action 객체가 생성됨

⇒ Action 객체가 Dispatch 함수의 인자로 전달
⇒ Dispatch 함수가 Action 객체를 Reducer 함수로 전달
⇒ Reducer 함수가 Action 객체의 값을 확인, 값에 따라 전역 상태 저장소 Store의 상태 변경
⇒ 상태가 변경되면 React가 화면을 다시 렌더링 함.


🟢 Store

: 상태가 관리되는 오직 하나뿐인 저장소의 역할로 Redux 앱의 state가 저장되어 있는 공간.

createStore 매서드를 이용해 Reducer를 연결해 Store 생성 가능


🟢 Reducer

Dispatch에서 전달받은 Action 객체의 type 값에 따라 상태 변경시키는 함수

Reducer는 외부 요인으로 인해 엉뚱한 값으로 상태가 변경되는 일 없는 순수함수여야 함.


🟢 Dispatch

Reducer로 Action 전달해주는 함수. (전달인자로 Action 객체 전달)


🟢 Action

어떤 액션을 취할 것인지 정의해 놓은 객체로 아래와 같은 형식으로 구성되며

type은 필수로 지정해주어야 함 (해당 객체가 어떤 동작 하는지 명시해줌)

type은 대문자와 Snake Case로 작성하고, 필요에 따라 payload 작성해 구체적 값 전달해줌.

// payload가 필요 없는 경우
{ type: 'INCREASE' }

// payload가 필요한 경우
{ type: 'SET_NUMBER', payload: 5 }

//보통 아래와 같이 Action 객체 생성하는 함수 만들어 사용하는 경우가 많음.

// payload가 필요 없는 경우
const increase = () => {
  return {
    type: 'INCREASE'
  }
}

// payload가 필요한 경우
const setNumber = (num) => {
  return {
    type: 'SET_NUMBER',
    payload: num
  }
}

🟢 Redux Hooks

위의 Store, Reducer, Action, Dispatch 개념들 연결시켜주는 역할.

useDispatch()

Action 객체를 Reducer로 전달해주는 Dispatch 함수를 반환하는 매서드.
Dispatch 설명할 때 사용한 dispatch 함수도 useDispatch 이용해 만듦.

useSelector()

컴포넌트와 state를 연결해 Redux의 state에 접근할 수 있게 해주는 매서드




예제


//파일 구조 
//Action 폴더 - index.js 
//Reducers 폴더 - index.js, initialState.js
//Store 폴더 = index.js
//App.js 
//index.js 

_______
//index.js : 프로바이더 엘리먼트 만들어주기 

import React from 'react';
import { createRoot } from 'react-dom/client';
import App from './App';
import { Provider } from 'react-redux';
import { store } from './Store';

const rootElement = document.getElementById('root');
const root = createRoot(rootElement);

root.render(
  <Provider store={store}>
  <App />
  </Provider>
);
_______
//App.js : useSelect, useDispatch 사용해 state와 dispatch 변수 만듦
//이벤트 핸들러 함수 plusNum, minusNum 작성 

import React from 'react';
import './style.css';
import { useSelector, useDispatch } from 'react-redux';
import { increase, decrease } from './Actions';

export default function App() {
  const state = useSelector((state) => state);
  const dispatch = useDispatch()

  const plusNum = () => {
    dispatch(increase())
  };

  const minusNum = () => {
    dispatch(decrease())
  };

  return (
    <div className="container">
      <h1>{`Count: ${state}`}</h1>
      <div>
        <button className="plusBtn" onClick={plusNum}>
          +
        </button>
        <button className="minusBtn" onClick={minusNum}>
          -
        </button>
      </div>
    </div>
  );
}

_____
//Store 폴더의 index.js : createStore 이용해 store 생성 

import { legacy_createStore as createStore } from 'redux';
import { counterReducer } from '../Reducers';

export const store = createStore(counterReducer);

_______
//Reducers 폴더의 initialState.js : counterReducer 함수에서 state의 초기값으로 사용할 initialValue를 변수로 만들어 export

export const initialState = 1;

____________
//Reducers 폴더의 index.js : counterReducer 함수 만들기 

import { initialState } from './initialState.js';
import { INCREASE, DECREASE, increase, decrease } from '../Actions';

export const counterReducer = (state = initialState, action) => {
  switch (action.type) {

    case INCREASE:
			return state + 1

    case DECREASE:
			return state - 1

    case 'SET_NUMBER':
			return action.payload

    default:
      return state;
	}
}

____
//Action 폴더의 index.js : action 객체를 생성하는 함수 increase, decrease 작성 

export const INCREASE = 'INCREASE';
export const DECREASE = 'DECREASE';
//type에 들어갈 문자열을 변수화 한 이유 
//1. 오타방지
//2. 자동완성 기능 사용 가능 => 코드 생산성 높임
//3. 코드 재사용하기 용이 

export const increase = () => {
  return {
    type: INCREASE,
  };
};

export const decrease = () => {
  return {
    type: DECREASE
  }
}




Flux 패턴

🤔 what is Flux ?

Flux is the application architecture that Facebook uses for building client-side web applications. It complements React's composable view components by utilizing a unidirectional data flow. It's more of a pattern rather than a formal framework, and you can start using Flux immediately without a lot of new code. Flux 공식문서

Flux는 페이스북이 클라이언트 사이드 웹 어플리케이션을 만드는 데 사용하는 앱 아키텍처이다. Flux는 단방향 데이터 흐름을 이용해 리액트의 컴포넌트 뷰 구성요소를 보완한다. 공식적인 프레임워크라기 보다는 패턴에 가깝다.

기존에 사용하던 MVC(Model-View-Controller) 패턴은 ViewController 하나가 화면 하나를 이끌어 가는 방식으로 컨트롤러가 모델도 관리하고, 뷰도 관리해야 해서 복잡한 구조가 됨.

Flux의 구조는 아래와 같다 (단방향 흐름)

어떤 action이 발생하면 dispatcher가 이를 받아와 해석, store에 저장된 정보에 변경을 주고, view로 다시 전달.

아래와 같이 사용자가 view 통해 액션을 발생시킬 수도 있는데, 그 경우에도 dispatcher가 이를 받아와서 같은 흐름을 만든다.




🤩 Flux 구조 속의 요소들 살펴보기

Action
: 어떤 행동(이벤트)이 발생했을 때 그 행동의 타입과 데이터를 객체로 만들어 dispatcher에게 전달.
(위에 리덕스 실습할 때 action 폴더의 index.js 에서 작성했던 것 처럼 !)

Dispatcher
: 모든 데이터 흐름 관리하는 중앙 허브. Store가 등록해놓은 Action 타입마다 실행될 콜백함수가 존재함. Action이 새로운 객체를 보내면 Store이 정해놓은 타입에 맞는 콜백 함수를 실행함.
Store의 데이터 조작은 오직 Dispatcher 통해서만 가능.
Store들 사이 의존성 있는 경우에도 순서에 맞게 콜백 함수 순차적 처리 가능하도록 관리.

Store(Model)
: 상태를 저장하는 저장소로 상태와 상태를 변경할 수 있는 매서드를 가짐. 어떤 타입의 Action이 발생했냐에 따라 그에 맞는 콜백 함수를 Dispatcher에 등록. Dispatcher가 콜백 함수 실행해 상태가 변경되면 View에게 변경 되었다고 알림.

View
: 리엑트에서 리엑트 컴포넌트에 해당함. 상태가 변경됨을 전달 받으면 최상위 View(Controller View)가 Store에서 데이터 가져와 자식 View들에게 내려보냄.
새로운 데이터 받은 view는 리렌더링함.
사용자가 view에 어떤 조작을 할 경우 그에 해당하는 Action 생성하기도 한다.






출처
공식문서 한글버전
참고 블로그 1
참고 블로그 2

profile
다시 일어나는 중

0개의 댓글