[REDUX] 상태관리

Ethan Jeong·2022년 9월 1일
0
post-thumbnail

상태관리의 필요성


  • 서로 다른 컴포넌트간에 데이터를 옮겨야 할 때 가장 간단한 방법은 props로 전달해주는 방법이 있다.
  • 보편적으로 컴포넌트들을 뿌려주는 곳에서 state의 변화를 저장하고 해당 데이터를 props로 줄곧 뿌려왔다.
  • 하지만 이는 props drilling 이라는 나의 불쌍한 머리에 드릴링을 하는 문제를 야기한다.
  • props drilling은 props를 전달하는 용도로만 쓰이는 컴포넌트들을 거치면서 데이터를 전달하는 현상을 의미한다.

props drilling의 문제점

  1. 코드의 가독성이 매우 나빠지게 됩니다. => props의 동선을 파악하면서 코드를 이해해야하기 때문
  2. 코드의 유지보수 또한 힘들어지게 됩니다. => side effect
  3. state 변경시 Props 전달 과정에서 불필요하게 관여된 컴포넌트들 또한 리렌더링이 발생합니다.
  4. 따라서, 웹성능에 악영향을 줄 수 있습니다.

그렇다면, 상태들을 저장소에 보관하고 필요할 때 꺼내 쓸 수 있다면, 얼마나 좋을까?

상태관리 라이브러리

  • 다행이도 선배 개발자님들의 엄청난 노력으로 이런 상태들을 관리할 수 있는 라이브러리들이 탄생됐다.
  • 여러 라이브러리가 있지만, 그 중에서 redux를 이번에 배웠다.

Redux (이덕수)


props를 이용했을 때의 A -> B component 데이터 흐름 redux를 이용했을 때의 A -> B component 데이터 흐름

Flux 패턴

  • MVC (Model, View, Controller)는 양방향 패턴이다. Model에 데이터를 저장하고, Controller를 이용하여 View로 데이터를 전달하여 사용자에게 보여진다. 만약 애플리케이션의 규모가 커졌을 때 데이터 흐름을 예측하기 어렵다는 단점이 있고 이를 보안하기 위해 flux패턴이 등장했다.
  • Flux는 사용자 입력을 기반으로 Action을 만들고 Action을 Dispatcher에 전달하여 Store(Model)의 데이터를 변경한 뒤 View에 반영하는 단방향의 흐름으로 애플리케이션을 만든다.
  1. Action은 타입과 데이터(payload)를 갖고있고, 타입으로 Reducer의 case를 조건으로 제시하여 원하는 로직을 실행시킬 수 있다.
  2. Dispatcher는 저장소 호출 명령(?)이다. store 안에 있는 reducer를 호출할 때 useDispatch 매서드를 사용한다.
  3. Store는 변경된 데이터를 View에게 알려주고 자신의 컴포넌트 트리에 속해 있는 자식 노드 모두를 다시 랜더링하게 한다.
  4. 말그대로 View인데 Flux에서의 View는 MVC의 뷰와는 달리 화면을 보여주는것 외에도 Controller의 성격또한 가지고 있다. 특히 최상위 View는 스토어에서 데이터를 가져와 이를 자식 View 로 내려보내주는 역할을 하고 있다.
    각 요소들은 단방향 흐름에서 순서대로 역할이 수행되고 또 다시 새로운 데이터 변경이 있으면 처음부터 이 흐름이 다시 시작된다.

(출처 : https://velog.io/@huurray/React의-탄생과-Flux-패턴에-대하여)

Redux 상태 관리 순서

  1. 상태가 변경되어야 하는 이벤트가 발생하면, 변경될 상태에 대한 정보가 담긴 Action 객체가 생성된다.
  2. Action 객체Dispatch 함수의 인자로 전달된다.
  3. Dispatch 함수Action 객체Reducer 함수로 전달해준다.
  4. Reducer 함수Action 객체의 값을 확인하고, 그 값에 따라 전역 상태 저장소 Store의 상태를 변경한다.
  5. 상태가 변경되면, React는 화면을 다시 렌더링 한다.

Redux에서는 Action → Dispatch → Reducer → Store 순서로 데이터가 단방향으로 흐르게 된다.

.
.
.

내 표정

... 코드로 진행을 정리해보자.

  1. 먼저 라이브러리를 index.js에 불러오자
import { Provider } from 'react-redux';
import { legacy_createStore as createStore } from 'redux';
  1. root.render() 에 <App/><Provider>로 감싸주고, Provider의 props로 store = {store} 를 넣어준다

  2. store 변수를 선언하고 createStore라는 메서드를 할당시킨다. const store = createStore()
    이때 createStore는 인자로 reducer 함수를 갖는다.

    reducer 란 현재 상태와 액션 객체를 받아, 필요하다면 새로운 상태를 리턴하는 함수이다. 액션 유형을 기반으로 이벤트를 처리하는 이벤트 리스너라고 생각하면 된다. 반드시 순수함수로 작성해야한다.

  3. reducer 함수를 작성해준다. 첫번째 인자에는 기존 state가 들어온다. 첫번째 인자에는 default value를 꼭 설정해준다. 그렇지 않을 경우 undefined가 할당되기 때문이다.
    const counterReducer = (state = count, action) => {}

중괄호 안에 로직을 작성한다.

const counrterReducer = (state = defaultValue, action => {
	switch(action.type){
    
    	case 'INCREASE':
    		return state + 1
            
        // 해당 되는 경우가 없을 땐 기존 상태를 그대로 리턴    
    	default:
    		return state
  1. Action Creator 함수를 작성하고 export 한다.
export const increase = () => {
  return {
    type: 'INCREASE'
  }
}
  1. app.js 파일에서 { useDispatch, useSelector }와 export된 Action 함수를 불러온다.
import { useDispatch } from 'react-redux';
import { increase } from './index.js'
  1. 각각 dispatch, state 변수명으로 메서드를 저장하고 함수에서 해당 변수의 인자로 원하는 Action을 넣어준다.
export default function App() {

  const dispatch = useDispatch()
  const state = useSelector((state) => state);
  const plusNum = () => {

    dispatch( increase() )
    
  };
  1. JSX에서 state를 조작하는 이벤트를 작성한다!

profile
효율매니아

0개의 댓글