Redux 상태 관리 라이브러리 알아보기

🐶·2021년 7월 11일
0

개념 정리

목록 보기
23/41
post-thumbnail
post-custom-banner

드디어 리덕스를 배우게 되었다!
이번주 금요일 오전엔 리덕스에 대한 개념을 정리하고, 오후엔 조그마한 커머스 페이지(장바구니에 상품 추가, 삭제 및 수량 조절 등의 기능을 가지고 있음)를 만들어보았다.
추상적인 개념들이 많기 때문에... 각 개념의 역할들을 충분히 숙지하기 위하여 이번 파트만큼은 achievement goals 내용을 아래와 같이 정리해보았다.

상태 관리 라이브러리는 왜 필요한가?


개발하고자 하는 프로그램의 컴포넌트 구성이 (2-3개의 레벨로 구성된 게 아니라) 굉장히 복잡해질 때, props로 상태를 전달해주는 것이 한계가 있을 것이다. props는 '리액트의 단방향 데이터 흐름 원칙에 따라' 최하위 컴포넌트에서 상위 state의 정보가 필요하다면,,,? state가 선언된 컴포넌트로부터 매 컴포넌트를 거쳐서 props가 아래 자식 컴포넌트로 전달되어져야 하기 때문이다. 코드 작성 뿐 아니라 상태 관리 자체가 굉장히 복잡하고 비효율적이다.

이러한 문제점을 해결하고자 리덕스와 같은 상태 관리 라이브러리가 등장하게 되었다.
Redux는 React의 관련 라이브러리, 혹은 하위 라이브러리가 아니다. Redux는 React 없이도 사용할 수 있는, 상태 관련 라이브러리이다.

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

Action

상태에 어떠한 변화가 필요하게 될 때 액션이란 것을 발생시킵니다. 이는 하나의 객체로 표현되는데 액션 객체는 다음과 같은 형식으로 이뤄져있다. 액션 객체는 type 필드를 필수적으로 가지고 있어야한다.

{
  type: "ADD_TODO",
  payload: {
    id: 0,
    text: "리덕스 배우기"
  }
}

액션 생성함수(action creator)는 액션을 만드는 함수이다. 단순히 파라미터를 받아와서 액션 객체 형태로 만들어준다.

export function addTodo(data) {
  return {
    type: "ADD_TODO",
    payload:
	//... ///
  };
}

이러한 액션 생성함수를 만들어서 사용하는 이유는 나중에 컴포넌트에서 더욱 쉽게 액션을 발생시키기 위함이다. 그래서 보통 함수 앞에 export 키워드를 붙여서 다른 파일에서 불러와서 사용한다.

리덕스를 사용 할 때 액션 생성함수를 사용하는것이 필수적이진 않다. 액션을 발생 시킬 때마다 직접 액션 객체를 작성할수도 있다.

Reducer

리듀서는 변화를 일으키는 함수이다. 리듀서는 두가지의 파라미터를 받아오고, 기본형태는 아래와 같다.

function reducer(state, action) {
  // 상태 업데이트 로직
  return alteredState;
}

리듀서는, 현재의 상태와 전달 받은 액션을 참고하여 새로운 상태를 만들어서 반환합니다. 이 리듀서는 useReducer 를 사용할때 작성하는 리듀서와 똑같은 형태를 가지고 있습니다.

리액트의 useReducer 에선 일반적으로 default: 부분에 throw new Error('Unhandled Action')과 같이 에러를 발생시키도록 처리하는게 일반적인 반면 리덕스의 리듀서에서는 기존 state를 그대로 반환하도록 작성해야합니다.

리덕스를 사용 할 때에는 여러개의 리듀서를 만들고 combineReducers라는 메소드로 루트 리듀서 (Root Reducer)를 만들 수 있습니다.

const rootReducer = combineReducers({
  itemReducer,
  notificationReducer
});

Store

리덕스에서는 한 애플리케이션당 하나의 스토어가 존재한다. 스토어 안에는, 현재의 앱 상태와, 리듀서가 들어가있고, 추가적으로 몇가지 내장 함수들이 있다.

dispatch

디스패치는 스토어의 내장메소드 중 하나이다. 디스패치는 액션을 발생 시킨다. dispatch 라는 함수에는 액션을 파라미터로 전달합니다 dispatch(action) 이렇게 호출을 하면, 스토어는 리듀서 함수를 실행시켜서 해당 액션을 처리하는 로직이 있다면 액션을 참고하여 새로운 상태를 만들어준다.




(출처: 코드스테이츠)

정리를 해보자면...
Action 객체는 Dispatch에게 전달되고, Dispatch는 Reducer를 호출해서 새로운 state를 생성한다.

Redux의 3가지 원칙. 주요 개념과 어떻게 연결되는지?

  • 리덕스는 전역의 상태 관리 라이브러리이다. 서로 다른 컴포넌트가 동일한 상태를 다룬다면, 이 출처는 오직 한 곳이어야 한다. 리덕스에서는 이 출처는 store이고 하나의 앱 당 하나의 store가 존재한다.
  • 리액트에서 setState() 함수의 사용으로만 state가 변경 가능하듯... 리덕스에서는 액션객체를 통해서만 state를 변경할 수 있다.
  • reducer라는 상태를 변경시켜주는 함수는 순수함수이다.

Presentational 컴포넌트와 Container 컴포넌트의 개념

Redux hooks(useSelector, useDispatch)를 사용해 store 를 업데이트할 수 있다.

useSelector는 리덕스의 상태값을 조회하기 위한 hook 함수이다. 컴포넌트와 state를 연결하는 역할을 한다. 컴포넌트에서 useSelector 메소드를 통해 store의 state에 접근할 수 있는 것이다.
useSelector의 전달인자로는 콜백 함수를 받으며 콜백 함수의 전달인자로는 state 값이 들어간다.

useDispatch는 Action 객체를 Reducer로 전달해주는 메소드입니다. Action 이 일어날만한 곳은 클릭 등의 이벤트가 일어나는 컴포넌트이다.

오늘 스프린트 과제로 만들어냈던 애플리케이션의 컴포넌트 구조는 아래와 같다.

중간레벨에 위치한 ShoppingCart라는 컴포넌트 내에서 아래와 같이 useSelector, useDispatch를 사용하였다.

import { useDispatch, useSelector } from 'react-redux'
//...//

export default function ShoppingCart() {

  const state = useSelector(state => state.itemReducer); //itemReducer로 인해 변경되는 'state'를 조회하여
  const { cartItems, items } = state //사용하기 쉽게 구조분해 할당...!
  const dispatch = useDispatch(); 

//...//
}

dispatch 메소드에 전달인자로 action 생성함수가 전달된다. 해당 action생성함수의 전달인자가 무엇인지 확인하여 onClick이벤트가 발생할 때 전달되는 전달인자와의 상관관계를 분명히 해야 한다(ex. item & item.id)

function ItemListContainer() {
  const state = useSelector(state => state.itemReducer);
  const { items, cartItems } = state; 
  const dispatch = useDispatch();

  const handleClick = (item) => {
    if (!cartItems.map((el) => el.itemId).includes(item.id)) { 
  
      dispatch(addToCart(item.id)) //TODO: dispatch 함수를 호출하여 아이템 추가에 대한 액션을 전달한다
    }
    
  return (
    //...//
        {items.map((item, idx) => <Item item={item} key={idx} handleClick={() => {
          handleClick(item) //이벤트 발생!
        }} />)} 
     
  );
}

참고한 자료
https://youtu.be/CVpUuw9XSjY :스프린트를 시작하기에 앞서 간단한 리덕스 튜토리얼을 직접 따라해보았다.
https://react-redux.js.org/api/hooks : 리액트 공식문서 내 hooks 파트

더 읽어보고 싶은 자료
https://velog.io/@dolarge/React-Container-Presenter-%ED%8C%A8%ED%84%B4 리액트에서 Presentational 컴포넌트와 Container 컴포넌트의 개념

profile
우당탕탕 개발일기📝🤖
post-custom-banner

0개의 댓글