react – 상태관리

학습 목표

* 상태 관리의 필요성 이해

* Redux(혹은 Flux Pattern)에서 사용하는 Action, Reducer, Store의 의미와 특징

* Redux의 3가지 원칙

* Presentational 컴포넌트와 Container 컴포넌트

* Redux hooks(useSelector, useDispatch)에 대한 이해 및 사용(store 업데이트)

상태 관리

프론트엔드 개발에서의 상태 관리

프론트엔드 개발에서 상태의 중요성

프론트엔드 개발에서 상태란?
UI에 동적으로 표현될 데이터

 

상태에 따라 어떤 화면이 영향을 받는지를 생각해야 한다
(ex. 쇼핑몰의 장바구니 를 생각하면서 연습해보기)

프론트엔드 개발에서의 Side Effect

함수(또는 컴포넌트)의 입력 외에도 함수의 결과에 영향을 미치는 요인
(ex. 네트워크 요청; 백엔드 API 요청)

Side Effect를 최대한 배제하고 컴포넌트 만들기

컴포넌트는 표현(presentation) 그 자체에 집중해야 하므로, 입력값이 fake 데이터라도 표현할 수 있어야 한다.
→ 굳이 fetch가 없어도 컴포넌트는 작동되어야 한다는 것
presentation 컴포넌트

불가피한 Side Effect와 상태

만약, 데이터가 서버에 있다면, 네트워크 요청(ex. Fecth) 때문에 오래 걸릴 수 있다
→ 불가피한 Side Effect(네트워크 요청)가 생김
→ 이러한 Side Effect에 의존적인 상태가 존재

 

데이터 로딩 여부(isLoading)와 같은 상태가 Side Effect에 의존적인 상태(state)가 된다
→ 데이터 전송 여부에 달렸으므로…
→ UI 구성 시에 항상 이런 Side Effect에 의존적인 상태도 고려해야 한다

상태의 적절한 위치 생각하기

상태를 두 가지로 구분해서 생각해보자

* 로컬 상태: 특정 컴포넌트 안에서만 관리되는 상태

* 전역 상태: 프로덕트 전체 혹은 여러 컴포넌트에서 관리되는 상태

로컬 상태

특정 컴포넌트 안에서만 관리되는 상태
→ 해당 컴포넌트 안에서만 영향을 끼친다

 

대부분의 경우 form을 이용한 상태는 로컬 상태!
→ input box, select box, radio button 등

전역 상태

프로덕트 전체 혹은 여러 컴포넌트에서 관리되는 상태
→ 다른 컴포넌트와 상태를 공유하고 영향을 끼친다

 

쇼핑몰 장바구니를 예로 들면, 상품 선택 여부에 따라 총 주문 금액을 업데이트해야 하고, 장바구니에 담긴 물품의 개수 등을 다른 컴포넌트에 전달해 줘야 함
상품 선택 여부, 장바구니에 담긴 물품, 데이터 로딩 여부 등이 전역 상태에 해당됨

 

서로 다른 컴포넌트의 사용하는 상태의 종류가 다르면, 출처가 달라도 되고 전역 상태가 아니라도 됨

 

but, 서로 다른 컴포넌트가 동일한 상태를 다룰 때는, 이 출처는 같아야 한다(서로 다른 출처x)
→ 출처가 다르다면 서로 동기화(sync)를 해야 하는 등 문제가 복잡해짐
→ 여기서 하나의 출처는 전역 공간

전역 상태에서의 데이터 무결성

  • 데이터 무결성데이터의 정확성을 보장하기 위해 데이터의 변경이나 수정 시 제한을 두어 안정성을 저해하는 요소를 막고 데이터 상태들을 항상 옳게 유지하는 것

 

무결성을 지키기 위해선
동일한 데이터항상 같은 곳에서 데이터를 가지고 오자!
→ Single source of truth(신뢰할 수 있는 단일 출처) 원칙

전역 상태 관리의 예

라이트 모드 / 다크 모드 테마 설정

다크 모드 설정하면 모든 컴포넌트에 이 모드가 적용이 됨
→ 테마 설정을 전역으로 관리해야 함

국제화(Globalization) 설정

유저가 사용하는 브라우저, 운영체제가 특정 언어를 사용하고 있음을 알아 내서, UI에 필요한 텍스트의 리소스를 따로 전역 상태로 관리해야 함

→ 모든 컴포넌트에서 사용자 언어로 표현되어야 하기 때문

history 기능(undo/redo)

포토샵에서 히스토리, undo/redo를 생각해보기
화면에 표시되는 모든 내용을 상태 객체로 저장한다면, 원하는 특정 상태를 바탕으로 컴포넌트 표현이 가능
→ 히스토리, undo/redo 작동 원리

상태 관리를 위한 각종 툴

상태 관리를 도와 주는 툴(상태 관리 라이브러리)

* React Context

* Redux

* MobX

상태 관리 툴의 장점

  • 전역 상태 저장소 제공
  • Props drilling 이슈 해결:

기존에는, <A>라는 컴포넌트에 상태가 있고, <I>라는 컴포넌트가 해당 상태를 사용한다고 하면, 그 중간에 존재하는 <C>, <G> 등은 굳이 name이라는 상태가 필요하지 않음에도, 컴포넌트에 props를 만들어 자식 컴포넌트에 넘겨주어야 했다

→ props drilling(프로퍼티 내려꽂기) 문제 발생
→ 어디서든 전역 상태 저장소에 접근할 수 있게 하면서 해당 이슈 해결

 

상태 관리 툴이 반드시 필요한 것은 아님
→ 대부분의 경우 React 공식 문서 내용(리액트로 사고하기)을 숙지하면 해결할 수 있다는 점!

 

기본 Hooks를 이용한 상태 관리 연습하기

* react-router-dom 을 이용한 CSR(Client Side Routing)

* useState를 이용해 상태 관리 사용

* 쇼핑몰 애플리케이션의 주요 기능 구현
- `장바구니 담기` 버튼 구현
- `장바구니 삭제` 버튼 구현
- `장바구니 상품 개수의 변동이 생길 때 마다, 상단 내비게이션 바에 상품 개수가 업데이트되도록 구현

작성한 코드 내용은 해당 git 참고

https://github.com/racyde/im-sprint-cmarket-hooks/tree/master/src


Redux

컴포넌트와 상태를 분리하여 로직을 짜게 도와 줌
→ 상태 변경 로직을 컴포넌트와 분리시켜, 표현에 집중한 보다 단순한 함수 컴포넌트 가능

 

→ 원리와 구조, 즉 분리시켜 구조화하는 설계에 집중해서 생각 할 것!

 

Redux는 react의 관련 라이브러리(하위 라이브러리)가 아니다!
Redux는 react없이도 사용할 수 있는 상태 관련 라이브러리다

학습 목표

* 상태 관리 라이브러리의 필요성 이해

* Redux(혹은 Flux Pattern)의 Action, Reducer, Store의 의미와 특징

* Redux의 3가지 원칙

* Presentational 컴포넌트와 Container 컴포넌트

* Redux hooks(useSelector, useDispatch)를 사용한 store 업데이트

Redux 소개

상태 관리를 위한 라이브러리

state 관리의 측면

react에서는 state를 class component 안에서 관리함

 

컴포넌트 간의 정보 공유(기존 react)
→ 형제 컴포넌트들 간에 데이터를 주고 받을 때, 부모 컴포넌트를 통해서 주고 받는다
→ 그런데 자식이 많아진다면? → 상태 관리가 매우 복잡해 진다

 

상태 관리 라이브러리인 Redux를 이용의 필요성!

Redux의 기본개념: 3가지 원칙

1. Single source of truth(신뢰할 수 있는 단일 출처): 동일한 데이터는 항상 동일한 곳에서 가져온다
→ 데이터를 저장하는 `Store`라는 하나의 공간이 존재한다는 뜻

2. State is read-only
→ 리액트에서 useState로 변경했듯이, Redux에서는 `Action`을 통해서만 변경 가능

3. Changes are made with pure functions
→ 변경은 순수 함수로만 가능하다
→ `Reducer`와 연결되는 개념

Redux의 기본 개념: Store

상태가 관리되는 오직 하나의 공간

 

Store 안에 앱에서 필요한 state들을 두고, 컴포넌트들이 state에 대한 정보가 필요하면, Store에 접근해서 그 정보를 가져올 수 있다

Redux의 기본 개념: Action

Simple JavaScript Object(자바 스크립트 객체)
→ Action은 자바 스크립트 객체 이다

 

그 객체 안에 type 등을 포함한 다양한 데이터들이 담김(타입을 꼭 지정해줘야 함)
Action 객체는 Store에게 애플리케이션의 데이터를 운반해 주는 역할을 함
(It carries a payload of information from your application to store)

// Store의 예시

{
    type: “ORDER”    // 타입은 꼭 지정해 줘야 함
    drink: {
        menu: “Americano”,
        size: “Grande”,
        iced: false
    }
}

Redux의 기본 개념: Reducer

현재 상태와 Action을 이용해 다음 상태를 만들어 낸다

Action을 통해 데이터를 Store에 전달할 수 있는데, 이 때 Reducer 를 거쳐서 가야 한다.

Action → Reducer → Store(Cur State → New State)
Dispatch

Action 객체가 Dispatch 메소드에게 전달되고, Dispatch는 Reducer를 호출해서 새로운 state 값을 생성

→ 이 공식을 따르는 이유? => 데이터는 한 방향으로만 흘러야 하기 때문(단방향 흐름)

 

Redux의 기본 개념 Overview

 

MapState props와 Redux Hooks를 통해서 이를 이러한 로직을 수행할 수 있는데,
Redux Hooks가 좀 더 직관적이고, 최근에 나온 방법이므로 이를 이용해서 알아 보자

Redux의 장점

 

  1. 상태를 예측 가능하게 만들어 줌
    → Reducer가 순수 함수이므로 다음 상태가 어떤 상태일지 쉽게 예측 가능
  2. 유지보수가 용이
    → 컴포넌트와 상태를 분리시킴으로서 코드 관리가 편함
  3. 디버깅에 유리
    → Action과 State의 로그 관리를 지원해 주므로, 디버깅에 유리(크롬 확장프로그램: Reduce DevTools 이용)
  4. 테스트를 하기 쉽다
    → 순수 함수를 사용하기 때문
복사했습니다!