리덕스로 상태 관리하기

빵호·2022년 1월 21일
0

리덕스(redux)

리덕스(reudx)는 자바스크립트를 위한 상태 관리 프레임워크이고 리덕스를 사용하는 이유는 다음과 같다.

  1. 같은 상태값을 다수의 컴포넌트에서 필요로 할 때
  2. 페이지가 전환되어도 데이터는 살아 있어야 할 때
  3. 알림창, 장바구니 같은 전역 컴포넌트의 상태값을 관리할 때
  4. 부모 컴포넌트 깊은 곳에 있는 자식 컴포넌트에 상태값을 전달할 때
  5. ... 등등등

리덕스 세 가지 원칙

1. 하나의 객체에 프로그램의 전체 상태값을 저장한다.

전체 상태값이 하나의 자바스크립트 객체로 표현되기 때문에 활용도가 높아진다. 하지만 프로그램의 전체 상태값을 리덕스로 관리하는 것은 쉬운 일이 아니기 때문에 특별히 로직이 복잡하지 않은 페이지에서는 컴포넌트의 상태값을 활용하는 게 생산성을 더 높일 수도 있다.

2. 상태값을 불변 객체로 관리한다.

상태값은 불변 객체로 관리하고 오직 액션 객체에 의해서만 변경되어야 한다.

const incrementAction = {
  type : 'INCREMENT', 1️⃣
  amount : 123, 2️⃣
};
const conditionalIncrementAction = {
  type : 'CONDITIONAL_INCREMENT', 1️⃣
  amount : 2, 2️⃣
  gt : 10, 
  lt : 100, 
};
store.dispatch(incrementAction); 3️⃣
store.dispatch(conditionalIncrementAction);

1️⃣ 액션 객체는 type 속성이 존재해야 하고 type 속성값으로 액션 객체를 구분한다.
2️⃣ type 속성값을 제외한 나머지는 상태값을 수정하기 위해 사용되는 정보다.
3️⃣ 액션 객체와 함께 dispatch 메서드를 호출하면 상태값이 변경된다.

리덕스의 상태값을 수정하는 방법은 액션 객체와 함께 dispatch 메서드를 호출하는 것이다. 상태값 수정에 불변 객체를 사용하는 이유는 전 후 값을 비교해서 변경 여부를 파악하기 쉽고, 상태값 변경을 빠르게 확인해 메모이제이션 같은 기능을 활용할 수도 있고 리액트의 렌더링 성능을 올리는 데도 유리하기 때문이다.

3. 오직 순수 함수에 의해서만 상태값을 변경해야 한다.

리덕스에서 상태값을 변경하는 함수를 리듀서(reducer)라고 부르고 리듀서의 구조는 다음과 같다.

(state, action) => nextState

리듀서는 이전 상태값과 액션 객체를 입력으로 받아서 새로운 상태값을 만드는 순수 함수이다. 순수 함수는 부수 효과(side effect)를 발생시키지 않아야 하고 같은 인수에 항상 같은 값을 반환해야 한다.

리덕스 주요 개념


리덕스에서 상태값이 변경되는 과정은 위와 같고 상태값을 변경하는 과정에서 거치게 되는 리덕스의 네 가지 요소를 살펴보자

액션(action)

액션(action)은 type 속성값을 가진 자바스크립트 객체이고 액션 객체를 dispatch 메서드에 넣어서 호출해 액션을 발생시킨다.

exprot const ADD = 'todo/ADD'; 1️⃣
exprot const REMOVE = 'todo/REMOVE';
exprot const REMOVE_ALL = 'todo/REMOVE_ALL';

exprot function addTodo({ title, priority }) { 2️⃣
  return { type : ADD, title, priority };
}
exprot function removeTodo({ id }) {
  return { type : REMOVE, id };
}
exprot function removeALLTodo() {
  return { type : REMOVE_ALL };
}

store.dispatch(addTodo({ title: '영화 보기', priority: 'high' })); 3️⃣
store.dispatch(removeTodo({ id: 123 }));
store.dispatch(removeAllTodo());

1️⃣ 액션 타입은 변수로 만들어 관리하고 type 속성값의 중복을 피하기 위해 접두사를 붙인다. 변수는 리듀서에서도 필요하기 때문에 export 한다.
2️⃣ 액션 생성자 함수를 필요한 인자와 함께 정의하고 외부에서 호출할 수 있도록 exprot 한다.
3️⃣ 액션 생성자 함수를 dispatch 메서드에 넣어서 호출해 액션을 발생시킨다.

리듀서

(state, action) => nextState

리듀서(reducer)는 액션이 발생했을 때 새로운 상태값을 만드는 함수이다.

const INITIAL_STATE = { todos : [] };

function reducer(state = INITIAL_STATE, action) { 1️⃣
  switch (action.type) { 
      // ...
    case REMOVE_ALL : 2️⃣
      return { 3️⃣
        ...state,
        todos : [],
      };
    case REMOVE : 
      return {
        ...state,
        todos: state.todos.filter(todo => todo.is !== action.id),
      };
      default : 4️⃣
      return state; 
  }
}

1️⃣ 스토어의 초기 상태값을 정의한다.
2️⃣ 각 액션 타입별로 case 문을 만들어서 처리한다.
3️⃣ 상태값은 불변 객체로 관리해야 하므로 수정할 때마다 새로운 객체를 생성한다.
4️⃣ 처리할 액션이 없으면 상택밧을 변경하지 않는다.

스토어

스토어(store)는 리덕스의 상태값을 가지는 객체이다.

const INITIAL_STATE = { value : 0 };
const reducer = createReducer(INITIAL_STATE, {
  INCREMENT : state => (state.valuye += 1),
});
const store = createStore(reducer);

let prevState;
store.subscribe(() => { 1️⃣
  const state = store.getState();
  if (state === prevState) { 2️⃣
    console.log('상태값 같음');
  } else {
    console.log('상태값 변경됨');
  }
  prevState = state;
});

store.dispatch({ type : 'INCREMENT' }); 3️⃣
store.dispatch({ type : 'OTHER_ACTION' }); 3️⃣
store.dispatch({ type : 'INCREMENT' });

1️⃣ subscribe 메서드를 이용해서 이벤트 처리 함수를 등록했고 스토어에 등록된 함수는 액션이 처리될 때 마다 호출된다.
2️⃣ 상태값이 변경됐는지 검사한다.
3️⃣ 'INCREMENT' 액션이 발생하면 상태값 변경됨이 콘솔에 찍힌다.
4️⃣ 등록되지 않은 액션이 발생하면 상태값 같음이 콘솔에 찍힌다.

profile
늘 한결같이 꾸준히

0개의 댓글