1주차발표자료 조찬기 - TECH-SHARING-STUDY/FE_STUDY GitHub Wiki

Redux VS Context API


image1


1. Redux를 사용한 방법


  1. store는 오직 하나만 존재한다.
  2. store의 state는 오직 action을 통해서만 변경할 수 있다.
  3. reducer는 pure function이다.

스토어를 만들어 최상단에 위치한다.

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(/*your root reducer*/);

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById("root")
);

상태를 변경할 때는 dispatch를 이용한다.

import React, { Component } from "react";
import { action1 } from "../actions";

class Button extends Component {
  doSomething(event) {
    this.props.store.dispatch(action1());
  }

  render() {}
}

export default Button;

사용할 때는 store.getState를 이용해 state를 사용

import React, { Component } from "react";

class Counter extends Component {
  render() {
    return (
      <div>
        <h1>Value : {this.props.store.getState().some.value}</h1>
      </div>
    );
  }
}

export default Counter;

2. Context API를 사용한 방법


Provider와 Consumer를 만들어 export해준다.

import React, { Component, createContext } from "react";

const Context = createContext(); // Context 를 만듭니다.
const { Provider, Consumer: SampleConsumer } = Context;

// Provider 에서 state 를 사용하기 위해서 컴포넌트를 새로 만들어줍니다.
class SampleProvider extends Component {
  state = {}; // state
  actions = {}; // setState 등을 이용한 state 변화 함수들

  render() {
    const { state, actions } = this;

    const value = { state, actions };
    return <Provider value={value}>{this.props.children}</Provider>;
  }
}

export { SampleProvider, SampleConsumer };

최상단 컴포넌트에 Provider를 감싼다.

import React from "react";
import { SomeProvider } from "./contexts/sample";

const App = () => {
  return (
    <SomeProvider>
      <InnerComponents />
    </SomeProvider>
  );
};

export default App;

전역 state를 사용하고 싶은 곳에서 Consumer 컴포넌트를 상위에 감싼다.

그 후 state로 상태 값을, actions로 상태 변경을 수행할 수 있다.

import React from "react";
import { SampleConsumer } from "../contexts/sample";

const Receives = () => {
  return (
    <SampleConsumer>
      {({ state, actions }) => (
        <Sends value={state.value} setValue={actions.setValue} />
      )}
    </SampleConsumer>
  );
};

export default Receives;

하나의 Provider, Consumer에 모든 전역상태를 다 때려박아야하나요??


여러개로 나눌 수도 있지만...

Provider가 많아지면 depth가 증가함

return (
  <SampleProvider>
    <AnotherProvider>
      <NewProvider>
        <WhatTheProvider>
          {... Provider 지옥}
        </WhatTheProvider>
      </NewProvider>
    </AnotherProvider>
  </SampleProvider>
);

createElement 를 이용해서 Provider를 하나로 합치는 것도 가능

import React from "react";
// Provider1, 2, 3 ... 이 있다고 할 때

// context props로 [Provider1, Provider2, ... ] 를 설정
const AppProvider = ({ contexts, children }) =>
  contexts.reduce(
    (prev, context) =>
      React.createElement(context, {
        children: prev,
      }),
    children
  );

최 상단의 Provider 들을 합친 하나의 Provider로 감싸기

Consumer의 사용은 동일합니다.

const App = () => {
  return (
    <AppProvider contexts={[SampleProvider, AnotherProvider]}>
      <div className="panes">
        <LeftPane />
        <RightPane />
      </div>
    </AppProvider>
  );
};

비교


React 와 Context API 기능 비교

기능 Redux Context API
전역상태저장 store 컴포넌트 (Provider)
저장소 state 변경 dispatch, reducer의 action 컴포넌트의 메소드
전역상태 사용 store.getState 컴포넌트 (Consumer)

Redux의 태생적 단점

Redux는 Redux를 사용하기 위해 프로젝트에 import 해야 할 라이브러리

라이브러리를 사용하는 것은 프로젝트의 번들 크기를 늘려 앱이 로드되는 데에 걸리는 시간을 증가시킨다.

라이브러리들을 적절한 이유 없이 사용해서는 안된다.

You Might Not Need Redux - Dan Abramov


  • 개발하고 있는 앱이 많은 상태를 저장할 필요가 없다면
  • 컴포넌트 구조가 과도한 prop drilling을 피할 수 있을만큼 단순하다면

모든 상태 관리 라이브러리는 사용할 필요가 없다.

(prop drilling : 프로퍼티 내리꽂기. 필요한 위치에 두기 위해서 프로퍼티를 내려 구멍을 내서 전달)


리액트를 사용을 권장하는 상황

  • 로컬 스토리지에 상태를 영속적으로 저장하고 시작할 때 다시 불러올 때
  • 상태를 서버에서 미리 채워서 HTML에 담아 클라이언트로 보내고 앱을 시작할 때
  • 사용자의 액션을 직렬화해서 상태와 함께 자동으로 버그 리포트에 첨부 (로깅)
  • 액션 객체를 네트워크를 통해 보내면 코드를 크게 바꾸지 않고도 협업 환경을 구현할 수 있습니다.
  • 실행취소 내역의 관리나 낙관적인 변경(optimistic mutations)을 코드를 크게 바꾸지 않고도 구현할 수 있습니다.
  • 개발할 때 상태 내역 사이를 오가고 액션 내역에서 현재 상태를 다시 계산하는 일을 TDD 스타일로 할 수 있습니다.
  • 개발자 도구에게 완전한 조사와 제어를 가능하게 해서 개발자들이 자신의 앱을 위한 도구를 직접 만들 수 있게 해 줍니다.
  • 비즈니스 로직 대부분을 재사용하면서 UI를 변경

Context API 의 약점

Context API는 high-frequency updates에 성능저하가 발생합니다.

Redux는 그렇지 않습니다

직접 확인해보세요

Vue.js - 다른 프레임워크와의 비교

(이렇게 자주 바뀌는 상황에서는 vue가 React보다 유리합니다.)


결론

  • 오직 전역 상태 관리를 위한다면 Context API를 사용하라.
  • 상태 관리 외에 여러 기능이 필요하다면 Redux 를 사용하라.
  • high-frequency한 어플리케이션의 경우 Context API를 사용하면 성능상 이슈가 있을 수 있다.

참고

React Redux vs Context API

Context API가 Redux를 대체할 수 있을까요?

⚠️ **GitHub.com Fallback** ⚠️