[TIL] Redux ?

lmimoh·2022년 11월 2일
0

TIL

목록 보기
19/26
post-thumbnail

Redux ?

Redux는 오픈 소스 자바스크립트 라이브러리로 예측 가능한 상태를 보관하는 컨테이너이다. 이는 MVC 패턴에서 프로젝트의 규모가 커질수록 생겨나는 수많은 View와 Model들로 인한 SideEffect를 방지하기 위해 탄생한 Flux 패턴을 기반 으로 탄생했다.


Redux의 필요성 ?

상태(satate)는 간단하게 표현하자면 데이터이다. 이는 CDD로 개발된 웹 APP의 컴포넌트 내에서 사용되는 데이터를 의미한다(유동적인).

프로젝트의 규모가 증가할수록 컴포넌트의 개수는 증가하게 되고, 이는 관리해야 할 state가 방대해지는 것 을 의미한다.

즉, 개발자는 웹 APP 내 존재하는 수 많은 상태(state)들을 일괄적으로 관리할 필요가 있었고 이를 위해 사용되는 것이 상태 관리 라이브러리이다.

CDD 개발을 지향하는 대표적인 라이브러리인 React에서 데이터(props)는 부모에서 자식으로만 전달되는 단방향 페턴이며, 자식 컴포넌트들 간의 다이렉트 데이터 전달은 불가능하다.

이때, 자식의 수가 너무 많아진다면 어떻게 될까?

최상위 요소에서 최하위 요소까지 데이터를 전달하기 위해 props는 사용되지 않는 컴포넌트들을 경유하여 도달 해야 한다.

=> Props Drilling 이슈 발생

이러한 전달 과정은 프로젝트의 복잡도가 증가할수록 데이터를 전달하기 위해 필요없는 경유를 거쳐야하며 이는 코드를 복잡하게 만들고 유지보수를 어렵게 만든다.

그렇다면, 상태 관리 라이브러리는 이를 어떻게 해결할까?

상태(state)를 일괄 보관하는 저장소를 보유하고 있는 상태 관리 라이브러리는 해당 상태를 필요로 하는 컴포넌트에 상태를 다이렉트로 전달 할 수 있다.

예를 들어, 기존의 A > B > C > D 의 방식이 A > store > D 방식으로 접근이 가능하게 한다. 이는 불필요한 데이터 경유 과정을 생략시켜준다.


Redux의 상태 관리 과정

  1. 상태가 변경되어야 하는 이벤트가 발생할 때, 상태를 변경시킬 정보가 담긴 Action 객체 가 생성된다.

이때, Action은 Reducer 함수가 어떤 액션을 취할 지 정의한 객체로 다음과 같은 형식으로 이루어진다.

// payload x
{ type : '취할_액션' }

// payload o
{ type : '취할_액션', payload : data }

여기서 type은 Action 객체 내에서 필수적으로 지정되어야 하며, 대문자와 Snake Case로 작성한다(SOME_ACTION).

이때, 필요에 따라 Reducer 함수가 해당 동작을 하기 위한 데이터를 전달 할 수 있으며 payload에 구체적인 값을 전달한다.

보통 Action 객체를 직접 작성하기보다는 객체를 생성하는 함수를 만들어 사용하는 경우가 일반적이며, 이를 액션 생성자(Action Creator) 라고 부른다.

const 취할_액션 = (data) => {
  return {
    type : '취할_액션',
    payload : data
  }
}
  1. 생성된 Action 객체는 Dispatch 함수의 인자로 전달되며, Dispatch 함수는 Reducer 함수로 전달한다.

이때, Dispatch는 Reducer로 Action을 전달하는 함수이다. Dispatch의 전달인자로 들어온 Action 객체를 전달한다.

// Action 객체를 직접 작성하는 경우
dispatch({ type : '취할_액션', payload : data });

// 액션 생성자(Action Creator)를 사용하는 경우
dispatch(취할_액션(data));

이때, React에서 dispatch는 React-Rdux에서 제공하는 Hooks 메서드 중 useDispatch()를 통해 생성 된다.

import { useDispatch } from 'react-redux'

const dispatch = useDispatch(); // dispatch 생성
dispatch(취할_액션(data)); // dispatch를 이용한 Reducer 함수 실행
  1. Reducer 함수는 Action 객체의 값을 확인하고, 그 값에 따라 Store 내의 상태(state)를 변경한다.

이때, Reducer는 Dispatch에게 전달받은 Action 객체를 토대로 상태(state)를 변경 시키는 함수이다.

// 숫자를 초기 상태로 동작하는 Reducer 예시
const count = 1;

const counterReducer = (state = count, action) => {
  // Action 객체의 type에 따라 분기를 나눈다.
  switch(action.type)
    case 'INCREASE' : return state + 1;
    case 'DECREASE' : return state - 1;
    case 'SET_COUNT' : return action.payload
    default : return state;
}
// 이때, reducer가 리턴하는 결과가 새로운 상태(state)가 된다.

또한, Reducer는 외부요인으로 인해 기대한 값이 벗어나지 않도록 순수함수 여야 한다.

  1. 변경된 Store 내 상태에 따라 웹 APP는 화면을 다시 렌더링한다.

이때, Store는 상태가 관리되는 유일한 저장소 를 의미한다. 이는 redux 앱의 createStore 메서드를 통해 생성될 수 있다.

import { createStore } from 'redux';

const store = createStore(rootReducer);

또한, React-Redux에서 제공되는 Hooks 메서드 중 useSelector()를 통해 컴포넌트는 store 내 상태(state)에 접근 할 수 있다.

import { useSelector } from 'react-redux'

const counter = useSelector(state => state);

Redux의 세 가지 원칙

Single source of truth
: 동일한 데이터는 항상 같은 곳 에서 가지고 와야 한다.
즉, Redux 내 데이터를 저장하는 공간은 Store 밖에 존재하지 않는다.

State is read-only
: 상태(state)는 읽기 전용 이며, Redux내 상태(state)의 직접 변경은 불가능 하며, 반드시 Action 객체와 Reducer 함수를 통해 상태(state)를 변경 해야 함을 의미한다.

Changes are made with pure finctions
: 변경은 순수함수로만 가능 하며, 상태가 예측하지 못한 값으로 변경되지 않도록 Reducer 함수는 순수함수로 작성되어야 함을 의미한다.


참조 :
Redux Tutorial
React-Redux Tutorial

profile
성장하는 개발자, 이민훈입니다.

0개의 댓글