Redux

Paul Mo·2022년 11월 25일
0
post-thumbnail

저번에 Recoil에 대해 배웠지만 사실은 그전에 Redux라는 것이 무엇인지 먼저 알 필요가 있다. 나는 앱을 처음 개발할 때 이미 다 만들어진 앱에 유지 보수하는 작업을 했었는데 앱을 구축하신 분들이 React에 대해 지식이 풍부하신 분들이 아니라 Redux를 사용하지 않는 상태였었다. 그래서 처음에는 state 관리를 그렇게 복잡하게 하는 것이 당연한 줄 알았다. 예를 들어 내 작업 중에서 환자의 문진을 받는 작업이 있었는데 문진은 많은 질문으로 이루어져 있는데 하나의 질문마다 자식 컴포넌트가 만들어져서 자식 컴포넌트로 데이터를 넘겨줄 때 props로 넘겨주면서 작업을 하다 보니 너무 많아져서 상태 관리를 하는 것이 너무 복잡해져 버리는 이슈가 있었다. 그래서 '보다 효율적으로 하는 방법이 없을까?' 리서치를 하다가 알아낸 것이 Redux였다.

state와 props에 대해
state는 component의 생명주기 동안 변경될 수 있는 정보를 담고 있는 객체이고 props는 부모 컴포넌트에서 자식 컴포넌트로 전달되는 데이터를 말한다.

Redux란?

공식문서에서는 Redux는 '액션'이라는 이벤트를 사용해서 상태를 관리하고 업데이트하는 패턴이자 라이브러리라고 하는데 간단하게 말하자면 Redux는 state를 편리하게 관리하기 위한 상태 관리 라이브러리라고 보면 된다. 위에서 언급했던 것처럼 앱의 규모가 커지게 돼서 자식 컴포넌트들이 많아지게 되면 같은 state를 여러 컴포넌트에서 사용하다 보니 상태 관리가 복잡해지게 되는데 Redux가 전역 상태 저장소를 제공함으로 써 어느 컴포넌트에서든 상태 저장소를 접근해서 필요한 state를 가져올 수 있게 해 준다. 그래서 자식 컴포넌트의 depth에 상관없이 상태 관리를 편리하게 할 수 있다는 것이다.

Redux 용어

1. Actions

Action은 type 필드를 가지고 있는 자바스크립트 객체이다. Application에서 일어나는 것을 설명하는 이벤트라고 생각하면 된다.

const addTodoAction = {
  type: 'todos/todoAdded',
  payload: 'Buy milk'
}

2. Action Creators

액션 객체를 반환하고 생성하는 함수이다.

const addTodo = text => {
  return {
    type: 'todos/todoAdded',
    payload: text
  }
}

3. Reducers

현재 상태와 액션 객체를 받아서 새로운 상태를 리턴하는 함수인데 액션 type을 기반으로 이벤트를 처리하는 이벤트 리스너라고 생각하면 된다.

const initialState = { value: 0 }

function counterReducer(state = initialState, action) {
  // Check to see if the reducer cares about this action
  if (action.type === 'counter/increment') {
    // If so, make a copy of `state`
    return {
      ...state,
      // and update the copy with the new value
      value: state.value + 1
    }
  }
  // otherwise return the existing state unchanged
  return state
}

4. Store

State를 저장해서 관리하는 저장소이다.

import { createStore } from 'redux'

function todos(state = [], action) {
  switch (action.type) {
    case 'ADD_TODO':
      return state.concat([action.text])
    default:
      return state
  }
}

const store = createStore(todos, ['Use Redux'])

store.dispatch({
  type: 'ADD_TODO',
  text: 'Read the docs'
})

console.log(store.getState())
// [ 'Use Redux', 'Read the docs' ]

5. Dispatch

액션 객체를 넘겨서 state를 업데이트 하는 유일한 방법이라고 한다. 쉽게 생각해서 이벤트 트리거라고 생각하면 된다.

store.dispatch({ type: 'counter/increment' })

console.log(store.getState())
// {value: 1}

6. Selectors

상태 값을 가져올 때 사용하는 함수이다.

const selectCounterValue = state => state.value

const currentValue = selectCounterValue(store.getState())
console.log(currentValue)
// 2

사용법

Redux의 개념은 처음 배울 때 정말 생소하고 복잡하고 어려웠던 것 같다. 위에서 배운 용어들은 대충 개념적으로 이해를 했지만 저것들을 어떻게 활용해서 사용해야 하는지 이해하고 실제 사용하기까지 쉽지 않았던 것 같다. 최대한 쉽게 내 나름대로 이야기를 해보자면, 애플리케이션에서 어떠한 이벤트가 발생했을 때 type과 payload 속성을 갖고 있는 action 객체가 dispatch 함수에 넣어져서 이벤트를 trigger 하면 reducer가 작동을 하여 store 안에 있는 새로운 state를 생성하는 방식이라고 생각하면 된다.

이렇게 Redux Flow를 설명하는 영상을 보아도 쉽게 이해하기 어렵기 때문에 나는 노마드 코더의 리덕스 101 무료 강의를 여러 번 반복해서 봤었다. Redux의 원리를 이해하고 사용하는데 도움이 많이 되었었다. 밑의 코드는 To Do List를 state로 만들어서 redux로 상태 관리하는 노마드 코더의 예제 코드인데 강의 내용의 코드이기 때문에 이를 참고해보고 강의를 들어보길 권한다.

import { createStore } from "redux";

const ADD = "ADD";
const DELETE = "DELETE";

const addToDo = text => {
  return {
    type: ADD,
    text
  };
};

const deleteToDo = id => {
  return {
    type: DELETE,
    id: parseInt(id)
  };
};

const reducer = (state = [], action) => {
  switch (action.type) {
    case ADD:
      return [{ text: action.text, id: Date.now() }, ...state];
    case DELETE:
      return state.filter(toDo => toDo.id !== action.id);
    default:
      return state;
  }
};

const store = createStore(reducer);

export const actionCreators = {
  addToDo,
  deleteToDo
};

export default store;

Redux의 종류라고 해야 될까? React의 상태 관리 라이브러리는 여러 가지가 있다. 순수 Redux에서 조금 더 사용하기 쉽게 만들어진 Redux Tool Kit, 저번에 사용했던 Recoil, 나는 한 번도 사용해 본 적 없는 mobx, 그리고 react에서 자체 제공하는 context api 등이 있다. 각 라이브러리마다의 장단점이 있기 때문에 당연하게도 나의 상황과 프로젝트의 환경에 맞게 사용하는 게 가장 좋을 것이다. 다음 글에는 내가 현재 사용하고 있는 Redux Tool Kit에 대해 포스팅해보도록 하겠다.

출처

profile
프론트 엔드 개발자

0개의 댓글