Previewlocked to source

이전에 Recoil 관련 강의를 듣다가 Context API는 상태 관리 도구라고 볼 수 없다고 했습니다. 이에 궁금한 점이 생겨 정리해보고자 합니다.

공식문서에서 React Context란?

  • 모든 컴포넌트에서 수동으로 props를 전달할 필요 없이 구성 요소 트리를 이용해 데이터를 전달합니다.
  • 트리의 모든 수준을 통해 명시적으로 props를 전달하지 않고도 구성 요소 간에 이와 같은 값을 공유하는 방법을 제공합니다.
  • 공식문서에서는 값을 "관리"하는 것에 대해서는 아무것도 언급하지 않고 값을 "전달" 및 "공유" 하는 것만을 나타냅니다.

Context 사용하기

  • 먼저 createContext 함수를 사용하여 **UserContext**라는 새로운 **Context**객체를 생성합니다.
  • UserStore 컴포넌트는 **props.children**을 포함하는 UserContext.Provider 컴포넌트를 반환합니다.
  • **UserContext.Provider**는 UserContext 객체를 이용해 value prop을 전달합니다.
import { createContext, useState } from "react";
export const UserContext = createContext(null);

const UserStore = (props) => {
    const [userId, setUserId] = useState("");
    const [password, setPassword] = useState("");

    return(
        <UserContext.Provider value={{
            userId,
            setUserId,
            password,
            setPassword
        }}>
            {props.children}
        </UserContext.Provider>
    );
};
export default UserStore;
  • 전역으로 상태 값을 가져오기 위해 **App.js**를 수정합니다.
  • **UserStore**를 먼저 렌더링하고 그 안에 **Router**와 **Routes**를 중첩하여 페이지 컴포넌트를 렌더링하게 합니다.
import './App.css';
import Login from './Login';
import Signup from './pages/Signup';
import Home from './pages/Home';
import { BrowserRouter as Router, Route, Routes} from "react-router-dom";
import UserStore from "./context/UserStore";

function App() {
    return (
        <UserStore>
            <Router>
                <Routes>
                    <Route path="/" element={<Login />} />
                    <Route path="/Signup" element={<Signup />} />
                    <Route path="/Home" element={<Home />} />
                </Routes>
            </Router>
        </UserStore>
    );
}
export default App;
  • 이제 컴포넌트에서 **UserContext**를 사용해 전역 상태 변수인 **username**과 **email**이 업데이트가 가능합니다.
import {UserContext} from "../context/UserStore";
import React, {useState, useEffect, useContext} from 'react';

const context = useContext(UserContext);
const {setUserId, setPassword} = context;

setUserId(inputId);
setPassword(inputPw);
  • 코드를 보면 Context가 어떤 것도 '관리' 하고 있지 않습니다.
  • **<UserContext.Provider>**로 파이프의 최상단에 무언가를 넣는다면 **userContext**를 외친 쪽으로 튀어나옵니다.
  • 이것은 상태 관리가 아닌 의존성 주입(Dependenty Injection)이라고 하며 하위 컴포넌트에서 값을 필요로 할 때 런타임 시점에 상위 컴포넌트의 어딘가로부터 값을 내려받는 것입니다.
  • 따라서 Context를 사용하는 주요 목적은 "prop-drilling"을 피하는 것입니다.

Redux란?

  • "action"이란 이벤트를 사용해 애플리케이션 상태를 관리하고 업데이트하기 위한 패턴 및 라이브러리
  • "전역"상태를 관리하는데 도움이 되며 전체 애플리케이션에서 사용해야 하는 상태에 대한 중앙 집중 저장소 역할을 합니다.
  • 제공하는 패턴과 도구를 사용하면 상태가 언제, 어디서, 왜, 어떻게 업데이트 되고 변경이 발생할 때 로직이 어떻게 작동하는지 더 쉽게 이해할수 있습니다.
  • 공식문서에서는 Redux가 구체적으로 "상태 관리"를 나타냅니다
  • Redux의 목적은 시간이 지남에 따라 상태가 어떻게 변하는지 이해하도록 돕는 것이라고 합니다.

Redux와 React

  • 리덕스는 모든 UI layer(React, Vue, Angular, vaninlla JS)와 함께 사용 가능
  • 하지만 대부분 React와 함께 쓰기 때문에 '리덕스'를 사용한다고 하면 Redux store + React-Redux library를 함께 쓰는 것을 말할 때가 많습니다.
  • React-Redux는 애플리 케이션의 모든 React 요소들이 Redux 저장소에 접근이 가능한데 이는 React-Redux 내부에서 Context를 사용하기 때문입니다.
  • 여기서 주의할 점은 React-Redux는 현재의 상태값을 Context를 통해 전달하는게 아니라 Redux 저장소 인스턴스만 전달한다는 점입니다.
  • 이것은 Context를 위에서 설명한 종속성 주입을 위해 사용하는 좋은 예입니다.
  • 이 덕분에 React-Redux는 내부적으로 Context를 사용하기 때문에 prop-drilling을 피하기 위해 사용될 수도 있습니다.

Redux를 사용하는 이유

  • UI레이어와 완전히 별개로 상태 관리 로직을 작성하고 싶은 경우
  • 다양한 UI레이어(ex. AngularJS에서 React로 마이그레이션되는 애플리케이션)간에 상태 관리 로직 공유
  • 작업이 전달될 때 Redux 미들웨어의 기능을 사용하여 추가 논리 추가
  • Redux 상태의 일부를 유지할 수 있음
  • 개발자가 재생할 수 있는 버그 보고서 활성화
  • 개발 중에 로직과 UI를 더 빠르게 디버깅

Context가 "상태 관리"가 아닌 이유

  • 상태 관리의 정의는 "시간이 지남에 따라 상태가 어떻게 변하는 가"입니다.
  • "상태 관리"는 다음과 같은 방법을 갖는 것을 의미합니다.
    • 초기값을 저장합니다.
    • 현재 값을 읽어옵니다.
    • 값을 업데이트 합니다.
  • useState와 useRedux Hooks은 상태관리의 좋은 예입니다.
    • Hook을 호출해 초기값을 저장합니다.
    • Hook을 호출해 현재 값을 읽습니다.
    • 제공된 setState 또는 dispatch 함수를 호출해 값을 업데이트 합니다.
    • 구성요소가 다시 렌더링되었기 때문에 값이 업데이트 된 것을 알 수 있습니다.
  • Redux와 MobX 또한 분명한 상태 관리입니다.
    • Redux는 root Reducer를 호출하여 초기 값을 저장하고 store.getState()을 사용하여 현재 값을 읽을 수 있습니다.
    • 또한 store.dispatch(action)를 사용하여 값을 업데이트하고 store.subscribe(listener)을 사용하여 저장소가 업데이트 되었음을 리스너에게 알립니다.
    • MobX는 스토어 클래스에 필드 값을 할당하여 초기 값을 저장하고 스토어의 필드에 액세스하여 현재 값을 읽을 수 있게하며 해당 필드에 할당하여 값을 업데이트하고 변경사항이 발생했음을 알립니다.
  • 하지만 Context는 그 자체로는 아무것도 "저장"하지 않습니다! 렌더링하는 상위 구성 요소는 <MyContext.Provider> Context에 전달되는 값을 결정하는 역할을 하며 해당 값은 일반적으로 React 구성 요소 상태를 기반으로 합니다.
  • 실제 "상태 관리"는 useState/useReducer Hook을 통해 이루어집니다.

Context와 Redux 비교

  • Context
    • 아무것도 저장하거나 "관리"하지 않습니다.
    • React 컴포넌트에서만 작동 합니다.
    • 타입에 관계없는 단일 값을 전달합니다.(원시, 객체, 클래스 등)
    • 단일 값을 읽을 수 있도록 합니다.
    • prop-drilling을 피하기 위해 사용할 수 있습니다.
    • React DevTools에서 Provider, Consumer가 있는 컴포넌트의 현재 값을 볼 수 있으나 상태 업데이트 히스토리는 보지 못합니다.
    • Context가 전달하는 값이 업데이트 되면 Consumer 컴포넌트도 자동으로 업데이트 되며 이를 스킵할 방법은 없습니다.
    • 사이드 이펙트를 처리하는 매커니즘이 전무하며 오로지 컴포넌트 렌더링에만 관여합니다.
  • React-Redux
    • 단일 값을 저장하고 관리합니다.(원칙적으로 객체입니다.)
    • 리액트 컴포넌트가 아닌 다른 UI와 함께 사용할 수 있습니다.
    • 단일 값을 읽을 수 있도록 합니다.
    • prop-drilling을 피하기 위해 사용할 수 잇습니다.
    • action을 dispatching하고 reducer를 작동시킴으로써 값을 업데이트 합니다.
    • DevTool에서 dispatch된 모든 action과 state 변화를 시간 순으로 볼 수 있습니다.
    • 사이트 이펙트를 발생시키기 위한 미들웨어를 사용할 수 있습니다.
    • 컴포넌트가 store 업데이트를 구독하고 store 상태의 특정한 일부를 추출하고 해당 값이 바뀌었을 때만 컴포넌트가 리렌더되도록 할 수 있습니다.

Context와 useReducer

  • Context vs Redux 논쟁에서의 문제점은 사람들이 "useReducer로 상태관리를 하고 Context로 값을 전달해준다"라고 말하는 것과 달리 그저 "나 Context 사용했어"라고만 말하기 때문에 Context로 상태를 관리한다는 잘못된 이야기가 지속된다고 봅니다.
  • Context + useReducer의 조합은 Redux + React-Redux와 닮아있습니다.
  • 두 조합은 아래의 공통점이 있습니다.
    • 저장되는 값
    • Reducer 함수
    • action, dispatch
    • 중첩 컴포넌트 내에서 값을 전달하고 읽는 기능
  • 반면 큰 차이점도 있습니다.
    • Context + useReducer는 리액트의 기능이므로 리액트에서만 사용 가능하지만 Redux 스토어는 모든 UI에 독립적으로 사용 가능합니다.
    • React DevTools을 사용하면 현재 Context 값을 볼 순 있지만 시간 순으로 지난 기록을 볼 순 없습니다.
    • Redux DevTools로는 디스패치된 모든 액션, 모든 액션의 컨텐츠, 액션 실행 후의 상태, 시간에 따른 상태의 차이를 볼 수 있습니다.
    • useReducer에는 미들웨어가 없습니다. useReducer와 useEffect를 함께 사용해 사이드 이펙트를 낼 수 있고 미들웨어와 비슷한 대안을 사용하려는 시도도 있었으나 기능과 효과면에서 리덕스 미들웨어에 비해서는 한계가 있습니다.
  • 얼핏 보기에는 비슷해보이나 절대 동일하지 않고 기능적으로 리덕스를 대체할 수는 없을 것입니다.

올바른 도구 선택

  • Context
    • prop-drilling 없이 중첩 컴포넌트에 값을 전해줍니다.
  • useReducer
    • reducer 함수를 사용하여 보통 수준의 복잡도를 지닌 리액트 컴포넌트의 상태를 관리합니다.
  • Context + useReducer
    • reducer 함수를 사용하여 보통 수준의 복잡도를 지닌 리액트 컴포넌트의 상태를 관리하고 prop-drilling 없이 중첩 컴포넌트에 값을 전달합니다.
  • Redux
    • reducer 함수를 사용하여 중간 또는 높은 수준의 복잡도를 지닌 리액트 컴포넌트 상태를 관리합니다.
    • 언제, 왜, 어떻게 상태가 변해왔는지 시간 순으로 추적합니다.
    • UI 레이어와 상태 관리 로직을 완벽히 분리합니다.
    • 서로 다른 UI 레이어 간 상태 관리 로직을 공유합니다.
    • 강력한 Redux 미들웨어 기능으로 액션 디스패치 시 로직을 추가합니다.
    • Redux 상태에 항시적으로 접근된 상태입니다.
    • 개발자가 버그 리포트를 재현할 수 있습니다.
    • 개발 시 로직과 UI를 빠르게 디버깅 할 수 있습니다.
  • Redux + React-Redux
    • 리액트 컴포넌트와 리덕스 스토어를 연결하여 모든 리덕스의 유즈 케이스를 구현할 수 있습니다.

결론

  • 단순히 prop-drilling을 피하고 싶다면 Context를 사용합시다
  • 컴포넌트 복잡도가 보통이거나 외부 라이브러리를 사용하고 싶지 않다면 Context + useReducer 조합을 사용합시다
  • 상태 변화 추적이 필요할 때, 상태 변화 시 특정 컴포넌트만 리렌더 하고 싶을 때, 사이드 이펙트를 강력하게 컨트롤하고 싶을 때는 Redux + React-Redux를 사용합시다

마치며

Context가 왜 상태관리가 될 수 없었는지 궁금했는데 지금 보니 Context가 값을 저장하지 못한다는 것을 깨닫게 되었습니다. 또 이에 대해 공부하면서 어떤 애플리케이션에 상태 관리 툴을 적절하게 사용해야 할지 추가적으로 공부하게 되었습니다. 앞으로 애플리케이션을 개발하면서 상태 관리를 정하는 데에 있어서 큰 도움이 될 것 같습니다.

Reference

Context API vs Redux - Medium Blogged Answers: Why React Context is Not a "State Management" Tool (and Why It Doesn't Replace Redux)

postsContext API가 상태 관리 도구라고 볼 수 없는 이유.md
010203040506070809101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
> 이전에 Recoil 관련 강의를 듣다가 Context API는 상태 관리 도구라고 볼 수 없다고 했습니다. 이에 궁금한 점이 생겨 정리해보고자 합니다.
# 공식문서에서 React Context란?
- 모든 컴포넌트에서 수동으로 props를 전달할 필요 없이 구성 요소 트리를 이용해 데이터를 전달합니다.
- 트리의 모든 수준을 통해 명시적으로 props를 전달하지 않고도 구성 요소 간에 이와 같은 값을 공유하는 방법을 제공합니다.
- 공식문서에서는 값을 "관리"하는 것에 대해서는 아무것도 언급하지 않고 값을 "전달" 및 "공유" 하는 것만을 나타냅니다.
# Context 사용하기
- 먼저 **`createContext`** 함수를 사용하여 **`UserContext`**라는 새로운 **`Context`**객체를 생성합니다.
- **`UserStore`** 컴포넌트는 **`props.children`**을 포함하는 **`UserContext.Provider`** 컴포넌트를 반환합니다.
- **`UserContext.Provider`**는 UserContext 객체를 이용해 **`value`** prop을 전달합니다.
```javascript
import { createContext, useState } from "react";
export const UserContext = createContext(null);
const UserStore = (props) => {
const [userId, setUserId] = useState("");
const [password, setPassword] = useState("");
return(
<UserContext.Provider value={{
userId,
setUserId,
password,
setPassword
}}>
{props.children}
</UserContext.Provider>
);
};
export default UserStore;
```
- 전역으로 상태 값을 가져오기 위해 **`App.js`**를 수정합니다.
- **`UserStore`**를 먼저 렌더링하고 그 안에 **`Router`**와 **`Routes`**를 중첩하여 페이지 컴포넌트를 렌더링하게 합니다.
```javascript
import './App.css';
import Login from './Login';
import Signup from './pages/Signup';
import Home from './pages/Home';
import { BrowserRouter as Router, Route, Routes} from "react-router-dom";
import UserStore from "./context/UserStore";
function App() {
return (
<UserStore>
<Router>
<Routes>
<Route path="/" element={<Login />} />
<Route path="/Signup" element={<Signup />} />
<Route path="/Home" element={<Home />} />
</Routes>
</Router>
</UserStore>
);
}
export default App;
```
- 이제 컴포넌트에서 **`UserContext`**를 사용해 전역 상태 변수인 **`username`**과 **`email`**이 업데이트가 가능합니다.
```javascript
import {UserContext} from "../context/UserStore";
import React, {useState, useEffect, useContext} from 'react';
const context = useContext(UserContext);
const {setUserId, setPassword} = context;
setUserId(inputId);
setPassword(inputPw);
```
- 코드를 보면 Context가 어떤 것도 '관리' 하고 있지 않습니다.
- **```<UserContext.Provider>```**로 파이프의 최상단에 무언가를 넣는다면 **```userContext```**를 외친 쪽으로 튀어나옵니다.
- 이것은 상태 관리가 아닌 의존성 주입(Dependenty Injection)이라고 하며 하위 컴포넌트에서 값을 필요로 할 때 런타임 시점에 상위 컴포넌트의 어딘가로부터 값을 내려받는 것입니다.
- 따라서 Context를 사용하는 주요 목적은 "prop-drilling"을 피하는 것입니다.
# Redux란?
- "action"이란 이벤트를 사용해 애플리케이션 상태를 관리하고 업데이트하기 위한 패턴 및 라이브러리
- "전역"상태를 관리하는데 도움이 되며 전체 애플리케이션에서 사용해야 하는 상태에 대한 중앙 집중 저장소 역할을 합니다.
- 제공하는 패턴과 도구를 사용하면 상태가 언제, 어디서, 왜, 어떻게 업데이트 되고 변경이 발생할 때 로직이 어떻게 작동하는지 더 쉽게 이해할수 있습니다.
- 공식문서에서는 Redux가 구체적으로 "상태 관리"를 나타냅니다
- Redux의 목적은 시간이 지남에 따라 상태가 어떻게 변하는지 이해하도록 돕는 것이라고 합니다.
# Redux와 React
- 리덕스는 모든 UI layer(React, Vue, Angular, vaninlla JS)와 함께 사용 가능
- 하지만 대부분 React와 함께 쓰기 때문에 '리덕스'를 사용한다고 하면 Redux store + React-Redux library를 함께 쓰는 것을 말할 때가 많습니다.
- React-Redux는 애플리 케이션의 모든 React 요소들이 Redux 저장소에 접근이 가능한데 이는 React-Redux 내부에서 Context를 사용하기 때문입니다.
- 여기서 주의할 점은 React-Redux는 현재의 상태값을 Context를 통해 전달하는게 아니라 Redux 저장소 인스턴스만 전달한다는 점입니다.
![](https://velog.velcdn.com/images/dbsghdql555/post/30202034-5021-41ea-afe7-83d3aa3790ae/image.png)
- 이것은 Context를 위에서 설명한 종속성 주입을 위해 사용하는 좋은 예입니다.
- 이 덕분에 React-Redux는 내부적으로 Context를 사용하기 때문에 prop-drilling을 피하기 위해 사용될 수도 있습니다.
# Redux를 사용하는 이유
- UI레이어와 완전히 별개로 상태 관리 로직을 작성하고 싶은 경우
- 다양한 UI레이어(ex. AngularJS에서 React로 마이그레이션되는 애플리케이션)간에 상태 관리 로직 공유
- 작업이 전달될 때 Redux 미들웨어의 기능을 사용하여 추가 논리 추가
- Redux 상태의 일부를 유지할 수 있음
- 개발자가 재생할 수 있는 버그 보고서 활성화
- 개발 중에 로직과 UI를 더 빠르게 디버깅
# Context가 "상태 관리"가 아닌 이유
- 상태 관리의 정의는 "시간이 지남에 따라 상태가 어떻게 변하는 가"입니다.
- "상태 관리"는 다음과 같은 방법을 갖는 것을 의미합니다.
- 초기값을 저장합니다.
- 현재 값을 읽어옵니다.
- 값을 업데이트 합니다.
- useState와 useRedux Hooks은 상태관리의 좋은 예입니다.
- Hook을 호출해 초기값을 저장합니다.
- Hook을 호출해 현재 값을 읽습니다.
- 제공된 setState 또는 dispatch 함수를 호출해 값을 업데이트 합니다.
- 구성요소가 다시 렌더링되었기 때문에 값이 업데이트 된 것을 알 수 있습니다.
- Redux와 MobX 또한 분명한 상태 관리입니다.
- Redux는 root Reducer를 호출하여 초기 값을 저장하고 store.getState()을 사용하여 현재 값을 읽을 수 있습니다.
- 또한 store.dispatch(action)를 사용하여 값을 업데이트하고 store.subscribe(listener)을 사용하여 저장소가 업데이트 되었음을 리스너에게 알립니다.
- MobX는 스토어 클래스에 필드 값을 할당하여 초기 값을 저장하고 스토어의 필드에 액세스하여 현재 값을 읽을 수 있게하며 해당 필드에 할당하여 값을 업데이트하고 변경사항이 발생했음을 알립니다.
- 하지만 Context는 그 자체로는 아무것도 "저장"하지 않습니다! 렌더링하는 상위 구성 요소는 ```<MyContext.Provider>``` Context에 전달되는 값을 결정하는 역할을 하며 해당 값은 일반적으로 React 구성 요소 상태를 기반으로 합니다.
- 실제 "상태 관리"는 useState/useReducer Hook을 통해 이루어집니다.
# Context와 Redux 비교
- Context
- 아무것도 저장하거나 "관리"하지 않습니다.
- React 컴포넌트에서만 작동 합니다.
- 타입에 관계없는 단일 값을 전달합니다.(원시, 객체, 클래스 등)
- 단일 값을 읽을 수 있도록 합니다.
- prop-drilling을 피하기 위해 사용할 수 있습니다.
- React DevTools에서 Provider, Consumer가 있는 컴포넌트의 현재 값을 볼 수 있으나 상태 업데이트 히스토리는 보지 못합니다.
- Context가 전달하는 값이 업데이트 되면 Consumer 컴포넌트도 자동으로 업데이트 되며 이를 스킵할 방법은 없습니다.
- 사이드 이펙트를 처리하는 매커니즘이 전무하며 오로지 컴포넌트 렌더링에만 관여합니다.
- React-Redux
- 단일 값을 저장하고 관리합니다.(원칙적으로 객체입니다.)
- 리액트 컴포넌트가 아닌 다른 UI와 함께 사용할 수 있습니다.
- 단일 값을 읽을 수 있도록 합니다.
- prop-drilling을 피하기 위해 사용할 수 잇습니다.
- action을 dispatching하고 reducer를 작동시킴으로써 값을 업데이트 합니다.
- DevTool에서 dispatch된 모든 action과 state 변화를 시간 순으로 볼 수 있습니다.
- 사이트 이펙트를 발생시키기 위한 미들웨어를 사용할 수 있습니다.
- 컴포넌트가 store 업데이트를 구독하고 store 상태의 특정한 일부를 추출하고 해당 값이 바뀌었을 때만 컴포넌트가 리렌더되도록 할 수 있습니다.
# Context와 useReducer
- Context vs Redux 논쟁에서의 문제점은 사람들이 "useReducer로 상태관리를 하고 Context로 값을 전달해준다"라고 말하는 것과 달리 그저 "나 Context 사용했어"라고만 말하기 때문에 Context로 상태를 관리한다는 잘못된 이야기가 지속된다고 봅니다.
- Context + useReducer의 조합은 Redux + React-Redux와 닮아있습니다.
- 두 조합은 아래의 공통점이 있습니다.
- 저장되는 값
- Reducer 함수
- action, dispatch
- 중첩 컴포넌트 내에서 값을 전달하고 읽는 기능
- 반면 큰 차이점도 있습니다.
- Context + useReducer는 리액트의 기능이므로 리액트에서만 사용 가능하지만 Redux 스토어는 모든 UI에 독립적으로 사용 가능합니다.
- React DevTools을 사용하면 현재 Context 값을 볼 순 있지만 시간 순으로 지난 기록을 볼 순 없습니다.
- Redux DevTools로는 디스패치된 모든 액션, 모든 액션의 컨텐츠, 액션 실행 후의 상태, 시간에 따른 상태의 차이를 볼 수 있습니다.
- useReducer에는 미들웨어가 없습니다. useReducer와 useEffect를 함께 사용해 사이드 이펙트를 낼 수 있고 미들웨어와 비슷한 대안을 사용하려는 시도도 있었으나 기능과 효과면에서 리덕스 미들웨어에 비해서는 한계가 있습니다.
- 얼핏 보기에는 비슷해보이나 절대 동일하지 않고 기능적으로 리덕스를 대체할 수는 없을 것입니다.
# 올바른 도구 선택
- Context
- prop-drilling 없이 중첩 컴포넌트에 값을 전해줍니다.
- useReducer
- reducer 함수를 사용하여 보통 수준의 복잡도를 지닌 리액트 컴포넌트의 상태를 관리합니다.
- Context + useReducer
- reducer 함수를 사용하여 보통 수준의 복잡도를 지닌 리액트 컴포넌트의 상태를 관리하고 prop-drilling 없이 중첩 컴포넌트에 값을 전달합니다.
- Redux
- reducer 함수를 사용하여 중간 또는 높은 수준의 복잡도를 지닌 리액트 컴포넌트 상태를 관리합니다.
- 언제, 왜, 어떻게 상태가 변해왔는지 시간 순으로 추적합니다.
- UI 레이어와 상태 관리 로직을 완벽히 분리합니다.
- 서로 다른 UI 레이어 간 상태 관리 로직을 공유합니다.
- 강력한 Redux 미들웨어 기능으로 액션 디스패치 시 로직을 추가합니다.
- Redux 상태에 항시적으로 접근된 상태입니다.
- 개발자가 버그 리포트를 재현할 수 있습니다.
- 개발 시 로직과 UI를 빠르게 디버깅 할 수 있습니다.
- Redux + React-Redux
- 리액트 컴포넌트와 리덕스 스토어를 연결하여 모든 리덕스의 유즈 케이스를 구현할 수 있습니다.
# 결론
- 단순히 prop-drilling을 피하고 싶다면 Context를 사용합시다
- 컴포넌트 복잡도가 보통이거나 외부 라이브러리를 사용하고 싶지 않다면 Context + useReducer 조합을 사용합시다
- 상태 변화 추적이 필요할 때, 상태 변화 시 특정 컴포넌트만 리렌더 하고 싶을 때, 사이드 이펙트를 강력하게 컨트롤하고 싶을 때는 Redux + React-Redux를 사용합시다
# 마치며
Context가 왜 상태관리가 될 수 없었는지 궁금했는데 지금 보니 Context가 값을 저장하지 못한다는 것을 깨닫게 되었습니다. 또 이에 대해 공부하면서 어떤 애플리케이션에 상태 관리 툴을 적절하게 사용해야 할지 추가적으로 공부하게 되었습니다. 앞으로 애플리케이션을 개발하면서 상태 관리를 정하는 데에 있어서 큰 도움이 될 것 같습니다.
#### Reference
[Context API vs Redux - Medium](https://olaf-go.medium.com/context-api-vs-redux-e8a53df99b8)
[Blogged Answers: Why React Context is Not a "State Management" Tool (and Why It Doesn't Replace Redux)](https://blog.isquaredsoftware.com/2021/01/context-redux-differences/)
hov_i [main] ⚡