React. Redux vs Context API

Redux 란?

리덕스는 상태의 중앙 관리를 위한 상태 관리 도구 이다.

전역 상태(Store)를 생성하고 상태(State)를 관리하기 위한 패턴 및 라이브러리

Redux Flow

https://miro.medium.com/max/700/0*Z18iLsM7Bf1xoNth.

Store

전역 상태를 저장하며, 이는 객체 형태로 저장되어 있다.

State(Read-only)를 변경할 수 있는 수단은 Action Type에 따른 Reducer 호출과 함께 새로운 State를 리턴한다.

$ npm install redux react-redux
// index.js
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";

import { createStore } from "redux";
import { Provider } from "react-redux";

const store = createStore();  // 전역 상태 저장소 생성

ReactDOM.render(
  // App 컴포넌트의 내 모든 컴포넌트에서 접근 가능하도록 Provider의 하위 컴포넌트로써 포함시킨다.
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById("root")
);

Action

상태에 어떠한 변화가 필요하게 될 때, 액션을 발생시킨다. 이는 하나의 객체로 표현하며, 액션 객체는 type 필드를 필수적으로 가지고 있어야한다.

dispatch(action)와 같이 호출하며, 이를 스토어가 트리거하여 리듀서는 정의된 action.type에 따른 함수를 실행시켜 액션을 처리한다.

{
  type: ADD_POST,
  // [, paylaod] => 때에 따른 데이터 전달할 수 있다.
}

Action Creator

액션 생성함수는 액션을 만드는 함수로 파라미터를 받아 액션 객체 형태로 만들어준다.

// ./reducers/posts.js

export const ADD_POST = post => ({
  type: "ADD_POST",
  post
});

이러한 액션 생성 함수를 만들어서 사용하는 이유는 이후 컴포넌트에서 더욱 쉽게 액션을 발생시키기 위함이다. 그렇기에 export 키워드를 붙여서 해당 컴포넌트에서 import 하여 사용한다.

Reducer

리듀서는 변화를 일으키는 함수이다.

// ./reducer/posts.js

const initialState = {
  posts: []
}

const reducer = (state = initialState, action) => {
  // 상태 없데이트 로직
  switch (action.type) {
    case "ADD_POST":
      return {
        ...state,
        posts: state.posts.unshift(action.data)
      }
    default:
      throw new Error("Unhandle Action");
  }
}

Context API

React Context는 근본적으로 [prop drilling](https://kentcdodds.com/blog/prop-drilling/) 문제점을 해결하기 위한 솔루션이다.

상태 관리 도구로서의 React Context

Built-In 이다

러닝 커브가 낮다

Context를 만들고, Provider를 통해 데이터 바인딩과 필요한 곳에서 꺼내 쓸 수 있는 Consumer 3개의 요소만 익히면 된다.

import React, { createContext } from "react";

const defaultValue = "light";
const ThemeContext = createContext(defaultValue);

const App = () => {
  <ThemeContext.Provider value="dark">
    <Toolbar />
  </ThemeContext.Provider>
}

const Toolbar = () => {
  <div>
    <ThemeButton />
  </div>
}

const ThemedButton = () => (
  <ThemeContext.Consumer>{(theme) => <Button theme={theme} />}</ThemeContext.Consumer>
);

Redux는 패턴 자체와 사용 규칙을 숙지해야 하며 middleware들을 비교하고 도입하는 것에 반면 진입 장벽이 굉장히 낮다.

전역적이지 않은 상태를 다루기 용이하다

대게 상태 관리 라이브러리가 그렇듯 Redux 또한 전역 상태에 포커스가 되어 있으며, 전역적이지 않은 상태를 다루는 것에는 취약하다.

https://chatoo2412.github.io/assets/posts/2019-11-12-react-context-as-a-state-management-tool/single-state-tree.png

위와 같이 React 컴포넌트 트리 중 특정 subtree(파란 사각형)에서만 공유되는 데이터가 존재할 때, Redux는 global state에 저장하고 접근해야 한다.

반면, Context는 오른쪽 그림과 같이 필요한 경우 Context를 만들어 제공할 수 있다.

Context의 단점

Context가 제공하는 Provider와 Consumer는 React 컴포넌트이기 때문에 wrapper hell이 발생한다.


Reference

Academind - Redux vs React’s Context API

cada(velog)

chatoo - 상태 관리 도구로서의 React Context

velpt - 벨로퍼트와 함께하는 모던 리액트


Written by@Jkun
...

GitHub