[React] Redux

nhchoi·2021년 11월 23일
0

React

목록 보기
3/3
post-thumbnail

Redux에 대해서 알아봅시다.

Redux

리액트 상태 관리 라이브러리
컴포넌트의 상태 업데이트 관련 로직을 다른 파일로 분리시켜서 효율적으로 관리할 수 있음
전역 상태를 관리할 때 효과적임

Context API + useReducer HookRedux는 매우 흡사
(redux도 reducer와 action이라는 개념을 사용함)

Redux 설치

# redux 기능을 제공해주는 모듈
npm install redux
# 리액트와 redux의 연동 기능을 제공해주는 모듈(connect, mapStateToProps ...)
npm install react-redux

Redux 개념

  • 액션
    상태에 변화가 필요할 땐 액션을 발생시킴 → 하나의 객체로 표현함
    type 필드는 필수적으로 가지고 있어야하고 그 외의 값들은 맘대로 넣어줘도 됨
{
  type: "CHANGE_INPUT",
  text: "안녕하세요"
}
  • 액션 생성 함수
    액션 객체를 만들어주는 함수
    → 변화가 있을 때마다 액션 객체를 만들어야 하는데 번거로움을 방지하기 위해 함수로 만듦

  • 리듀서
    변화를 일으키는 함수
    → 액션을 만들어서 발생시키면 리듀서가 현재 상태(state)와 전달받은 액션(action) 객체를 파라미터로 받아옴
    그 두 값을 참고하여 새로운 상태를 만들어 변환

    useReducer Hook을 사용할 때 작성하는 리듀서와 같은 형태임
    → 그러나, useReducer에서는 default로 에러 처리를 하는 것이 일반적이지만, 리덕스의 리듀서에서는 기존 state를 그대로 반환해야함

  • 스토어
    리덕스에서는 한 어플리케이션 당 하나의 스토어를 만듦
    → 현재의 앱 상태와 리듀서, 추가적인 내장 함수가 포함되어있음

// 스토어 만들기
const store = createStore(reducer);
// 현재 상태 불러오기
const state = store.getState();
  • 디스패치
    스토어의 내장함수 중 하나
    액션을 발생시키는 것. 파라미터로 액션을 전달함 → eg) dispatch(action)
    호출을 하면, 스토어는 리듀서 함수를 실행시켜 해당 액션을 처리하는 로직이 있다면 액션을 참고하여 새로운 상태를 만들어 줌

  • 구독(subscribe)
    스토어의 내장함수 중 하나
    함수 형태의 값을 파라미터로 받아옴. 함수를 전달해주면, 액션이 디스패치 되었을 때 마다 전달해준 함수가 호출됨.
    → 쓸 일 거의 없음.


그래서, 위 개념들이 어떻게 연결 되는건지?

상태 값을 사용하는 컴포넌트가 스토어구독(스토어에게 함수 전달)
→ 스토어는 상태 값이 변경되면 전달받은 함수 호출
상태 값을 변경하는 컴포넌트가 스토어에 dispatchaction 전달
→ action은 상태 변화 시 참조할 수 있는 객체
스토어는 액션의 타입을 참조하여 리듀서를 통해 새로운 상태를 만들어서 반환함
상태의 변화가 생기면 구독하고 있던 컴포넌트에게 알림(구독할 때 전달받은 함수)
→ 새로운 상태를 받고 리렌더링

Redux의 3가지 규칙

  1. 단일 스토어
    하나의 어플리케이션에선 단 한 개의 스토어를 만들어서 사용함
  2. 읽기 전용 상태
    리덕스에선 불변성을 유지해주어야 함.
    내부적으로 데이터가 변경되는 것을 감지하기 위해 swallow equality 검사를 하기 때문
  3. 리듀서는 순수 함수
    • 리듀서 함수는 이전 상태와 액션 객체를 파라미터로 받는다.
    • 파라미터 외의 다른 값엔 의존하면 안된다.
    • 이전 상태는 절대로 건드리지 않고, 변화를 일으킨 새로운 상태 객체를 만들어서 반환한다.
    • 똑같은 파라미터로 호출된 리듀서 함수는 언제나 똑같은 결과값을 반환한다.

Context API와 리덕스의 차이점

  1. 미들웨어
    리덕스에는 미들웨어라는 개념이 존재 → 주로 비동기 작업을 처리할 때 많이 사용
    리덕스로 상태관리를 할 땐 리듀서 함수를 사용하는데, 미들웨어를 사용하면 액션 객체가 리듀서에서 처리되기 전에 원하는 작업을 할 수 있음
  2. 함수, Hook
    connect 함수 : 리덕스의 상태 또는 액션 생성 함수를 컴포넌트의 props로 받아올 수 있음
    useSelector, useDispatch, useStore : 손쉽게 상태를 조회하거나 액션을 디스패치 할 수 있음
  3. 하나의 상태
    Context API를 사용할 땐 기능별로 Context를 만들어서 사용하는 것이 일반적
    → 리덕스에서는 모든 전역 상태를 하나의 커다란 상태 객체에 넣어서 사용함.
    매번 새로운 Context를 만드는 수고로움을 덜 수 있음


리덕스 모듈

액션 타입, 액션 생성함수, 리듀서가 모두 들어있는 자바스크립트 파일

  • 액션 타입 : 액션 타입은 대문자로 정의, 문자열 내용은 모듈 이름/액션 이름의 형태로 작성 (나중에 프로젝트가 커졌을 때 액션의 이름이 충돌되지 않게 하기 위해서)
  • 액션 생성 함수 : export 키워드 씀 (다른 파일에서 이 함수를 가져다 쓸 수 있게 하기 위해서)
  • 리듀서 함수 : initial 값을 지정할 수도 있음. 현재 상태를 참조하여 새로운 객체를 생성하여 반환하는 코드를 작성하면 됨. export default 키워드 사용하여 내보냄

  • 루트 리듀서 : createStore 함수를 사용하여 스토어를 만들 때는 리듀서를 하나만 사용해야함 (리듀서가 여러 개라면 하나로 합쳐줘야 함. 리덕스의 combineReducers 함수 사용)
  • Provider 컴포넌트 : 리액트 컴포넌트에서 스토어를 사용할 수 있도록 App 컴포넌트를 react-redux에서 제공하는 Provider 컴포넌트로 감싸준다.
  • 컨테이너 컴포넌트 : 리덕스 스토어와 연결된 컴포넌트. 스토어에 접근하여 원하는 상태를 받아오고, 액션도 디스패치함. HTML 태그들을 사용하지 않고 다른 presentational 컴포넌트를 불러와서 사용함.
  • connect 함수 : 컨테이너 컴포넌트와 리덕스를 연동하기위해 사용함.
connect(mapStateProps, mapDispatchToProps)(연동할 컴포넌트)
const makeContainer = connect(mapStateProps, mapDispatchProps)
makeContainer(연동할 컴포넌트)

위 두 코드는 완전히 같은 의미

connect 함수를 호출하면 또 다른 함수가 반환됨
그 함수에 연동할 컴포넌트를 파라미터로 전달하면 리덕스와 연동된 컴포넌트가 만들어짐

  • mapToStateProps : 리덕스 스토어 안의 상태를 컴포넌트의 props로 넘겨주기 위해 설정하는 함수

  • mapDispatchToProps : 액션 생성 함수를 컴포넌트의 props로 넘겨주기 위해 사용하는 함수

    • bindActionCreators : 액션 생성 함수의 갯수가 많아진다면, 각 함수를 생성하고 dispatch로 감싸는 작업이 번거로울 수도 있음. bindActionCreators 함수는 리덕스에 내장되어있는 함수이며, 액션함수를 자동으로 설정해주어 dispatch 과정을 손쉽게 해준다.
    • connect 함수의 두 번째 파라미터에 액션 생성 함수를 객체 형태로 넣어주면 connect 함수가 내부적으로 bindActionCreators 작업을 해줌

리덕스 파일 구조

  • actions, constants, reducers 패턴
    • 액션타입, 액션 생성함수, 리듀서 함수를 담는 세 개의 디렉터리를 만들고 그 안에 기능별로 파일을 하나씩 만드는 방식
    • 가장 일반적인 구조이나, 새로운 액션을 만들때마다 세 종류의 파일을 모두 수정해야 하기 때문에 불편한 점이 있음
  • Ducks 패턴
    • 액션 타입, 액션 생성 함수, 리듀서 함수를 기능별로 파일 하나에 몰아서 다 작성하는 방식

그래서

리덕스를 언제 써야할까?

  • 프로젝트의 규모가 클 때
    • 단순히 글로벌 상태를 사용하고자 한다면 Context API로 충분할 수 있음
  • 비동기 작업을 자주 수행할 때










참조 링크
https://react.vlpt.us/redux/
profile
👩‍💻

0개의 댓글