[React] Redux를 알아보자 - 리액트 없는 리덕스, 그 잡채만 써보자고! 리덕스의 작동원리, 개념, 리덕스 사용이유
**생활코딩 영상을 보며 제가 이해하는대로 정리해보았습니돠
대표적인 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에 해당하는 객체값이 전달된다. 예시는 이렇다.
리듀서는 state를 가공하는 가공자라고 할 수 있다.
(**return 에 Object.assign()을 쓴 이유는 immutable 객체에 대한 내용을 공부하면 이해 가능하다)
2-2 "subscribe를 이용해서 render함수를 호출하면 화면이 갱신된다" - 리듀서로 state를 바꾸고 dispatch는 이제 두번째 일을 한다.
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
리덕스 키워드
- 액션 (Action)
상태에 변화가 필요할 때 발생시킴 (객체하나로 표현)
type을 필수로 그외의 값들은 개발자 마음대로 생성 - 액션 생성함수 (Action Creator)
컴포넌트에서 더욱 쉽게 액션을 발생시키기 위함
필수 아님 - 리듀서 (Reducer)
변화를 일으키는 함수
현재의 상태와 액션을 참조하여 새로운 상태를 반환 - 스토어 (Store)
한 애플리케이션당 하나의 스토어
현재의 앱 상태와, 리듀서, 내장함수 포함 - 디스패치 (dispatch)
스토어의 내장함수
액션을 발생 시키는 것 - 구독 (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" }));