React-Redux 기초

React-Redux 기초

Redux


Redux란?

  • React에서는 React 컴포넌트에서 각자 상태(state)를 관리하는데 Redux를 사용하게 되면 State를 별도의 Store에서 State 관리하고 React Component에서는 해당 state를 보여주기만 한다.

1. Redux가 필요한 이유


상태 관리의 필요성

  • 애플리케이션 상태 관리는 버그를 최소화하면서 잘 만들어진 경험(UX)을 사용자에게 제공하는 데 절대적으로 중요하다.

  • 애플리케이션의 상태를 관리하기 위한 견고하고 안정적인 솔루션을 제공한다.

  • 혼란스럼게 흩어져 있는 상태를 체계화 하여 애플리케이션을 관리하도록 도와준다.

  • React의 경우 컴포넌트 간의 데이터 관리를 props를 사용하여 부모에서 자식으로 넘겨주어 관리하는데 이렇게 관리를 하게 되면 복잡하게 되는데 Redux는 이러한 상태관리를 독립된 Store(저장소)를 생성하여 상태를 관리하게 됩니다.

  • redux의 장점

    • 예측 가능하다.
    • 중앙에서 체계적으로 관리가능하다.
    • debug가 쉽다.
    • 유연하게 다른 라이브러리, 프레임워크와 사용이 가능하다.

2. Redux의 작동 흐름 (3원칙)

  1. 애플리케이션 상태는 모두 한 곳에서 집중 관리된다.(동기화 필요 없음)
  2. 상태는 불변 데이터 이며, 오직 액션 만이 상태 교체를 요청할 수 있다. (예측 가능)
  3. Reducer(리듀서 함수)를 통해 상태의 최종 값만 설정한다.(단순환)
  • App에서 상태를 교체해야할 경우 Action을 요청하고 Action은 Reducer 함수에게 상태 변경을 요청한다. Reducer에서 상태 변경이 이루어진 후 Store에 저장을 한 후 Store에 저장된 데이터를 App에 다시 전달한다. 특징으로 App에서 Action으로 요청하기 떄문에 예측이 가능하고 App상태 변화의 흐름에 디버깅이 쉽다는 점이다.
    redux 작동 맵

3. Redux의 아키텍처 (설계 구성 방식)

  • Redux 구조

    • Store(저장소) : 애플리케이션 상태 관리
    • State(상태)
    • Action(액션) : 미리 정의된 정보 패키지 전달된 정보 선택 포함
    • Reducer(리듀서 함수) : 액션 수신/상태 업데이트, 하나 이상 리듀서 결합 가능
    • Subscription(서브 스크립션) : 업데이트 된 상태를 애플리케이션에 전달
    • Component(뷰) : 앱 상태를 조작(사용자)
  • store에 연결된 모든 컴포넌트(뷰)는 상태에 따라서 좌우된다.

  • 컴포넌트(뷰)가 상태를 변경하려 할때는 Action으로 상태 변경 요청을 해야한다.

  • Action은 Reducer함수에 요청을 하여 상태 변경을 해주고 Reducer를 통해 Store의 state를 변경시켜준다.

redux 작동 맵

4. 스토어란

  • App의 상태를 나타내는 많은 key:value 쌍으로 구성된 정보를 가진 하나의 큰 JS객체이다.
  • Redux 스토어는 애플리케이션의 상태를 관리하고, .getState()(상태를 가져올 때 사용),.dispatch()(Action 호출할 때 사용),.subscribe()(상태 변경을 구독할 때 사용)같은 메서드를 제공한다.

스토어 객체 생성 — Redux.createStore() 메서드

1
2
3
4
5
6
7
import { createStore } from 'redux';

// Redux 스토어 생성
// 리듀서 함수를 전달 받음
const reudcer = (state, action) => {};

const store = createStore(reducer);
  • 다음과 같이 conosle.log(store)를 하였을때 함수 안에 getState(), dispatch(), subscribe(), replaceReducer()를 포함하는 객처를 생성하여 준다.

5. 상태(state)란

  • Redux Store에서 관리하는 상태(데이터) 입니다.
  • 일반적으로 State 또는 initState 이름으로 설정한다.
  • 상태는 Reducer의 첫번째 인자로 전달된다.
  • 상태 트리는 불변 상태 즉 순수한 상태를 가져야한다. 레이어 상태는 리듀서로 처리 될 때 예측 가능하기 떄문이다. 상태 관리는 불변 데이터 관리를 참고해야한다.

상태(state) 가져오기 — store.getState() 메서드

  • store를 등록 후에 .getState()를 사용하여 등록된 상태 정보를 가져올 수 있다.
1
2
3
4
5
6
7
8
9
10
11
import { createStore } from 'redux';

const initialData = 'Redux State Data';

const reudcer = (state, action) => {
return state;
};

// 이때 Reducer는 함수를 return해주어야 하기 떄문에 다음과 같이 사용해주어야 한다.
const store = createStore(() => reducer(initialData));
console.log(store.getState());

6. 액션(action)이란?

  • 액션은 App에서 “상태 변경을 설명하는 정보”를 스토어로 보내는 JS객체로 Redux에 알려 변화를 이끌어낸다.
  • 상태 값을 변경(교체)할 경우, 교체 할 상태 값을 리듀서(함수)에 보낼 수 있다.

액션(action) — type, payload 속성을 가진 객체

  • type은 대문자로 작성해주는 것이 관례이다.
1
2
3
const increaseCountAction = { type: 'INCREASE_COUNT' };
const decreaseCountAction = { type: 'DECREASE_COUNT' };
const resetCountAction = { type: 'RESET_COUNT', payload: 0 };
  • 실제 사용 방법
    • 다음과 같이 사용할 때 Action을 통해 type을 정의해주고 Type에 따라 state(상태)를 변경시켜 줄 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import { createStore } from 'redux';

const initialData = 'Redux State Data';

// 정적으로 처리하는 방법
const changeDataAction = {
type: 'CHANGE_DATA',
};

// 동적으로 처리하는 방법
const changeAnotherDataAction = {
type: 'CHANGE_Another_DATA',
payload: 'change_payload Data',
};

const reudcer = (state = initialData, action) => {
console.log(action);

switch (action.type) {
case 'CHANGE_DATA':
state = 'Redux Change State Data';
breake;

case 'CHANGE_Another_DATA':
state = action.payload;
breake;
}
return state;
};

const store = createStore(initialData);

// 이때 출력값은 initailData가 된다.
console.log(store.getState());

// setTimeOut을 통해 reducer안에 Action의 type에 대해 알아본다.
widow.setTimeout(() => {
store.dispatch(changeDataAction);
}, 3000);

widow.setTimeout(() => {
store.dispatch(changeAnotherDataAction);
}, 5000);

액션 타입을 별도로 관리

  • 액션 타입을 별도로 관리하는 파일을 만들어 상수로 관리하는 것이 유지보수 하기 좋다.
1
2
3
4
5
// store/action/actionTypes.js

export const INCREASE_COUNT = 'INCREASE_COUNT';
export const DECREASE_COUNT = 'DECREASE_COUNT';
export const RESET_COUNT = 'RESET_COUNT';
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
import { createStore } from 'redux';

const initialData = 'Redux State Data';

// actionType.js
const CHANGE_DATA = 'CHANGE_DATA';
const CHANGE_Another_DATA = 'CHANGE_Another_DATA';

// action.js
// 정적으로 처리하는 방법
const changeDataAction = {
type: CHANGE_DATA,
};

// 동적으로 처리하는 방법
const changeAnotherDataAction = {
type: CHANGE_Another_DATA,
payload: 'change_payload Data',
};

const reudcer = (state = initialData, action) => {
console.log(action);

switch (action.type) {
case CHANGE_DATA:
state = 'Redux Change State Data';
breake;

case CHANGE_Another_DATA:
state = action.payload;
breake;
}
return state;
};

const store = createStore(initialData);

// 이때 출력값은 initailData가 된다.
console.log(store.getState());

// setTimeOut을 통해 reducer안에 Action의 type에 대해 알아본다.
widow.setTimeout(() => {
store.dispatch(changeDataAction);
}, 3000);

widow.setTimeout(() => {
store.dispatch(changeAnotherDataAction);
}, 5000);

7. 리듀서(reducer) — 순수한 함수

  • 모든 Redux App은 Reducer(리듀서)를 구현해야한다는 공통점이 있다.
  • 애플리케이션 상태를 교체하는 함수를 말한다. 이전 상태(prevState)새로운 상태(state)로 교체한다.
1
2
3
4
5
리듀서 = (상태, 액션) {
// 액션 타입 분석
// 이전 상태 -> 다음 상태로 교체
// 다음 상태 변환
}

Reducer 특성

  • 전달 받은 매개변수 state, action에 변형을 가하면 안된다.
  • 네트워킹(API호출 <- 비동기 통신) 또는 라우팅을 변경하면 안된다.
  • 반드시 반환 값은 새로운 상태이어야 한다.

순수한 함수란?

  • 순수 함수는 반환 값이 전달 인자 값에만 의존하는 함수를 말한다. 순수 함수는 새로운 값을 계산한다. 동일한 유형의 인자 집합을 사용해 순수 함수를 호출하면 예측 가능한 결과 값을 확신할 수 있다.

  • 순수 함수는 전달 된 인자 값을 변경하지 않는다.

  • 다음과 같은 함수를 순수한 함수라고 한다.

1
2
const square = x => x * x;
const sqareAll = items => items.map(square);
  • 순수하지 못한 함수는 DB 또는 네트워크 통신 및 DOM 조작과 같은 경우를 말한다.
1
2
3
4
5
6
7
const square = x => {
updateXInDatabase(x);
return x * x;
};
const sqareAll = items => {
items.forEach(item => (item = square(item)));
};
Author

YoungHea Kim

Posted on

2021-05-20

Updated on

2021-05-20

Licensed under