나의 React 개발기록/React

[React] Redux를 알아보자 - 리액트 없는 리덕스, 그 잡채만 써보자고! 리덕스의 작동원리, 개념, 리덕스 사용이유

써머름 2022. 11. 21. 15:50
728x90
반응형

**생활코딩 영상을 보며 제가 이해하는대로 정리해보았습니돠

대표적인 react의 상태관리 라이브러리인 Redux ....!

내가 2주안에 추가 기능 개발 진행해야하는 ..사내 프로젝트가..Redux와 Saga..가 사용되어있어서 .. 🥲

불가피하지만 아주 빠르게 공부를 해서 잡티없이 개발을 진행해보자 ! 

 

Redux를 사용해야하는 경우

- 컴포넌트들의 조합으로 이루어진 프로젝트에서 props로 다양한 상태를 관리하기 복잡할 때

- 컴포넌트의 트리가 복잡하거나, 여러 다른 방식으로 업데이트가 되어야 할 때 

 

 

리덕스의 작동원리 큰 흐름 !

위의 예시를 들어서 순서의 흐름대로 봐보자 ! 
1. submit 버튼을 눌렀을때 예시로 적어준 "create"라는 타입으로  dispatch에 전달한다.
2. 그 때, dispatch는 두가지 일을 할 수 있다. 
( reducer를 호출해서 state의 값을 바꾼다. 그 다음에는 subscribe를 이용해서 렌더함수를 호출하면 화면이 갱신된다)

2-1 "reducer를 호출해서 state의 값을 바꾼다" - dispatch를 이용해서 reducer를 어떻게 다루는지 봐보자 

- dispatch가 reducer를 호출할때 두개의 값을 전달한다. state의 값과, action에 해당하는 객체값이 전달된다. 예시는 이렇다.

reducer가 받는값은 state랑 action이다. action의 타입이 create인 경우에 대하여 return하는 state값을 정의해주고 있다.

리듀서는 state를 가공하는 가공자라고 할 수 있다.

(**return 에 Object.assign()을 쓴 이유는 immutable 객체에 대한 내용을 공부하면 이해 가능하다)

2-2  "subscribe를 이용해서 render함수를 호출하면 화면이 갱신된다" - 리듀서로 state를 바꾸고 dispatch는 이제 두번째 일을 한다.

dispatch가 subscribe에게 render를 다시 하라고 요청한다. 그러면 render함수는 getstate를 통해 새로운 값을 가져와 화면에 그려준다.

submit부터 흐름을 보면 생소한 용어이지만 과정을 이해할 수 있다 ! 

 

~ 큰 흐름 ~

* 리덕스는 state값에 직접 접근할 수가 없다 ( 정확한 상태관리를 하기위한 태초의 이유때문)

* 우리는 화면에서 state가 변경되는 action이 일어났을때 dispatch를 통해 reducer(함수)를 호출한다 

* reducer는 1.state를 바꿔줄것이다. 2. 화면을 다시 그리는 render함수를 호출한다

* render 함수는 getState를 통해 state값을 가져오고 화면에 다시 그려준다

 

Redux를 사용하는 이유

- 각각의 컴포넌트간의 의존성이 높을때, 한 컴포넌트에서 props를 수정하거나 삭제하면 연결된 코드가 얽혀있어 오류가 발생한다.

- 따라서 모든 컴포넌트를 수정해줘야하지만, redux를 통해 중앙 집중형 관리를 하면,

각각의 컴포넌트는 action(상태바뀜)을 store에 dispatch(통보)만 하여 값을 전달 받는 방식으로 상태관리를 할 수 있다. 

- 이에 따라 각각의 컴포넌트에서 다른 변화된 값이 나온다면, store에 subscribe(구독) 즉 등록하게 되면, state가 바뀔때마다 dispatch받을 수 있기 때문에 다른 컴포넌트와의 연결없이 자신의 모양을 자유롭게 바꿀 수 있습니다. 
- 즉, 중앙 상태값 관리 로직을 공유하지만 각 컴포넌트 안에 있는 상태별로 다르게 작동하는 모듈의 독립성은 보장받을 수 있다. 

- 서로 의존관계가 사라지게 때문에 각자의 컴포넌트에서 집중하여 작업을 할 수 있다. 그것이 바로 decoupling (디커플링) ! 

 

벨로퍼트 리덕스 참고자료 : https://react.vlpt.us/redux/01-keywords.html 

 

1. 리덕스에서 사용되는 키워드 숙지하기 · GitBook

1. 리덕스에서 사용되는 키워드 숙지하기 리덕스를 사용하게 될 때 앞으로 접하게 될 키워드들을 미리 알아봅시다. 이 키워드들 중에서 대부분은 이전에 useReducer를 사용해볼때 접해본 개념이기

react.vlpt.us

리덕스 키워드

  1. 액션 (Action)
    상태에 변화가 필요할 때 발생시킴 (객체하나로 표현)
    type을 필수로 그외의 값들은 개발자 마음대로 생성
  2. 액션 생성함수 (Action Creator)
    컴포넌트에서 더욱 쉽게 액션을 발생시키기 위함
    필수 아님
  3. 리듀서 (Reducer)
    변화를 일으키는 함수
    현재의 상태와 액션을 참조하여 새로운 상태를 반환
  4. 스토어 (Store)
    한 애플리케이션당 하나의 스토어
    현재의 앱 상태와, 리듀서, 내장함수 포함
  5. 디스패치 (dispatch)
    스토어의 내장함수
    액션을 발생 시키는 것
  6. 구독 (subscribe)
    스토어의 내장함수
    subscribe 함수에 특정 함수를 전달해주면, 액션이 디스패치 되었을 때 마다 전달해준 함수가 호출
    (리액트에서는 connect 함수 또는 useSelector Hook 을 사용)

리덕스의 규칙 

 

1.하나의 애플리케이션 안에는 하나의 스토어를 가져야 한다.

  • 하나의 App에는 하나의 스토어를 만들어 사용한다.
    • 필수는 아니지만 권장하지 않는다.
    • 개발 도구를 활용할 수 없기 때문이다.

2. 상태는 읽기 전용이다.

  • 기존의 상태를 수정하지 않고 새로운 상태를 생성하여 업데이트한다. (교체의 개념)
  • 이를 통해 불변성을 유지할 수 있다. → 데이터의 변경을 감지하기 위해서는 내부 데이터까지 전부 찾아봐야 하는데 이 경우 시간이 너무 오래 걸린다. → 따라서 기존 상태의 객체를 새로운 객체로 변경하면 객체의 주소가 다르므로 변경을 쉽게 감지하는것이 가능하다.

3. 리듀서는 순수한 함수여야 한다.

  • 리듀서는 이전 상태와 액션 객체를 파라미터로 받는다.
  • 이전의 상태는 건들이지 않고 변화로 새로운 상태 객체를 만든다.
  • 동일 인풋에 대한 동일 아웃풋이 보장되어야 한다. (순수해야 한다.)

하지만 그렇지 않은 경우도 존재한다. 이때 리덕스 미들웨어라는 것을 사용한다.

 

기본 리덕스 작동원리를 이해하기위한 실습 코드 ↓

import { createStore } from "redux";

// 초기상태를 정의한다
const initialState = {
  count: 0,
  myText: "",
  myList: [],
};

// 액션타입을 정의한다 주로 대문자이다
const INCRE = "INCRE";
const DECRE = "DECRE";
const CHANGE_TEXT = "CHANGE_TEXT";
const ADD_LIST = "ADD_LIST";

//액션 생성함수 정의
const increase = () => ({
  type: INCRE,
});
const decrease = () => ({
  type: DECRE,
});
const changeText = (text) => ({
  type: CHANGE_TEXT,
  text,
});
const addList = (item) => ({
  type: ADD_LIST,
  item,
});

// 리듀서를 만들어보자
function reducer(state = initialState, action) {
  switch (action.type) {
    case INCRE:
      return {
        ...state,
        count: state.count + 10,
      };
    case DECRE:
      return {
        ...state,
        count: state.count - 1,
      };
    case CHANGE_TEXT:
      return {
        ...state,
        text: action.myText,
      };
    case ADD_LIST:
      return {
        ...state,
        list: state.myList.concat(action.item),
      };
    default:
      return state;
  }
}

const store = createStore(reducer);

console.log(store.getState());

// 스토어안데 상태가 바뀔때마다 호출되는 listener함수

const listener = () => {
  const state = store.getState();
  console.log("리스너 발동", state);
};
const aaa = store.subscribe(listener);

store.dispatch(increase());
store.dispatch(decrease());
store.dispatch(changeText("들어가니?"));
store.dispatch(addList({ id: 1, text: "dkssud" }));

 

728x90
반응형