• useReducer, Context, Redux 차이

    2022. 11. 16.

    by. JJo 😊

    리액트 상태 관리에 대해 리덕스까지 개념을 익히고 나니 혼란이 왔다.. 상태관리에 도움을 주는 기능에는 useReducer, Context, Redux…들이 있는 것 같은데.. 언제 어떨 때 이 중 하나를 골라 쓰면 되는 건지, 결국 다 상태 관리 역할을 하는 것 같은데..그럼 이 기능들을 이렇게 분리하고 있는 이유는 뭔지..? 에 대한 궁금함이 생겨 이들의 차이점에 대해 찾아보았다.

    📌 React Context

    일단 리액트에서 props를 전달하는 방식은 탑-다운(부모에서 자식으로)으로 진행이 된다. 전달되는 props의 양이 많아지고 컴포넌트의 깊이가 깊어지면 관리가 번거로워질 수 있다. Context Tree는 컨텍스트 안에 포함된 모든 레벨에서 명시적으로 props를 전달하지 않고, 어디에서든 상태 값에 접근할 수 있는 방법을 제공해준다.

    목적 및 사례

    Context는 실제로 아무것도 관리하지 않는다! 단순히 값을 전달하는 역할을 한다. 개념적으로는 종속성 주입의 한 형태로 자식 구성 요소에 특정한 상태 값이 필요하다는 것은 알지만 값을 직접 생성하거나 설정하지 않는다. 대신 상위 요소가 런타임에 해당 값을 전달한다고 가정한다. Context의 목적은 prop-drilling을 피하는 것이다.

    🤔 prop-drilling 이란?

    prop-drilling은 props를 오로지 하위 컴포넌트로 전달하는 용도로만 쓰이는 컴포넌트들을 거치면서 컴포넌트 트리의 한 부분에서 다른 부분으로 데이터를 전달하는 과정이다. prop-drilling은 prop 전달이 3~5개 정도의 적은 양이라면 이 자체가 문제가 되지는 않는다. 하지만 prop 전달이 10개, 15개 등 더 많은 과정을 거치게 되면 prop을 추척하기 힘들어진다. 이는 유지보수도 어렵게 만드는 요인이 될 수 있다. 그래서 과도한 prop-drilling을 피하기 위해 여러 방법 중 상태관리 라이브러리를 사용할 수 있다.

    Context는 ‘상태관리’가 아니다?!

    상태관리는 시간이 지남에 따라 상태가 변경되는 방식을 의미한다. 아래와 같은 경우를 상태관리라 한다.

    • 초기 값을 저장한다.
    • 현재 값을 읽을 수 있다.
    • 값 업데이트가 가능하다.

    Context의 경우 위의 조건을 충족하지 않기 때문에 상태관리 도구라고 할 수 없다. Context는 전달되는 값을 결정하는 역할을 하는 수단일 뿐 사실상 상태관리 자체는 리액트 컴포넌트의 useStateuseReducer로 하게 되는 것이다.

    React useState와 useReducer가 상태 관리의 좋은 예이다.

    • hook 을 호출하여 초기 값 저장
    • hook 을 호출하여 현재 값을 읽는다
    • 제공된 setState, dispatch 함수를 호출하여 값을 업데이트한다.
    • 구성 요소가 re-render 되었기 때문에 값이 업데이트 됐음을 확인 할 수 있다.
    • 마찬가지로 Redux, Mobx 도 위의 조건들을 충족하기 때문에 상태관리라 할 수 있다.

    📌 Redux

    리덕스는 애플리케이션 전체에 대한 상태 중앙 저장소 역할을 하고, 액션이라는 이벤트를 사용하여 애플리케이션의 상태를 예측 가능한 방식으로 업데이트하기 위한 패턴, 라이브러리이다. 리덕스에서 제공하는 패턴과 도구들을 사용하면 상태가 언제, 어디서, 어떻게, 왜 업데이트 되었는지 쉽게 이해할 수 있다. reducer함수를 이용하여 상태 변경을 예측하게 만든다.

    리덕스의 목적은 시간이 지남에 따라 상태 값들이 어떻게 변하는지 이해할 수 있도록 돕는 것이다.

     

    리액트에서 리덕스를 사용할 때 사용되는 React-Redux 라이브러리는 리덕스에서 상태 값을 읽고 action 을 리액트 컴포넌트에게 전달하여 리덕스 저장소와 상호 작용 할 수 있도록 도와주는 UI 바인딩 레이어이다.

    React-Redux 를 사용하면 애플리케이션의 모든 요소들이 리덕스 저장소에 접근이 가능한데 이는 React-Redux 내부에서 Context를 사용하기 때문이다. 여기서 주의할 점은 React-Redux 는 현재의 상태값이 아닌 Context를 통해 Redux 저장소 인스턴스만 전달한다는 점이다.

    목적 및 사례

    • ui 레이어와 분리된 상태 관리 로직 작성이 필요할 때
    • 서로 다른 ui 계층 간에 상태 공유가 필요할 때
    • Redux 미들웨어 기능을 빌려 액션이 전달될 때 추가적인 로직이 필요할 때
    • Redux 상태의 유지
    • dev tool을 이용한 버그 디버깅

    Redux와 Context의 차이

    👉 최적화

    리덕스에서는 컴포넌트에서 글로벌 상태의 특정 값을 의존하게 될 때 해당 값이 바뀔 때에만 리렌더링이 되도록 최적화가 되어있다. 즉, 글로벌 상태 중 의존하지 않는 값이 바뀌게 될 때에는 컴포넌트에서 낭비 렌더링이 발생하지 않는다.

    반면 Context에는 이러한 성능 최적화가 이뤄지지 않았다. 컴포넌트에서 만약 Context의 특정 값을 의존하는 경우, 해당 값 말고 다른 값이 변경 될 때에도 컴포넌트에서는 리렌더링이 발생하게 된다.

    따라서, Context를 사용하게 될 때에는 관심사의 분리가 굉장히 중요하다. 서로 관련이 없는 상태라면 같은 Context에 있으면 안되며, 따로 분리해야 한다.

    👉 여러 편리한 라이브러리 제공

    리덕스에서는 redux-sagaredux-thunkredux-devtools 등 다양한 추가 라이브러리를 통해 우리가 조금 더 상태 관리를 수월하게 할 수 있도록 도와준다.

    👉 미들웨어

    리덕스에는 미들웨어라는 개념이 존재한다.

    👉 글로벌 상태

    Context는 글로벌 상태를 관리할 때 일반적으로 기능별로 Context를 만들어 사용하는 것이 일반적이다. 반면, 리덕스에서는 모든 글로벌 상태를 하나의 커다란 객체에 넣어서 사용한다. 때문에 매번 Context를 새로 만드는 수고로움을 덜 수 있다.

    📌 Context 와 useReducer

    useReducer 는 Redux + React-Redux 와 비슷한 구조를 가지고 있다.

    • 값의 저장
    • reducer 함수
    • action 전달
    • 값을 전달하고 컴포넌트에서 읽는 방법

    그러나 기능과 동작에는 많은 차이점이 존재한다.

    • Context + useReducer 는 Context를 통해 현재 상태 값을 전달하는데 의존한다. React-Redux는 Context를 통해 현재 Redux 스토어 인스턴스를 전달한다.
    • useReducer 의 경우 새로운 상태 값을 생성 할 때 해당 Context 내부에 포함된 컴포넌트들이 상태값의 일부에만 관심이 있더라도 강제로 re-render 되기 때문에 성능 문제가 발생 할 수 있다. React-Redux 를 사용하면 저장소 상태의 특정 부분만 사용하고 해당 값이 변경 될 때만 re-render 할 수 있다.
    • Context + useReducer 는 React 의 기능이기 때문에 React 외부에서는 사용이 불가하다. Redux 는 UI 독립적이기 때문에 React 와 별도로 사용이 가능하다.
    • React DevTools 를 사용하면 현재의 상태 값은 볼 수 있지만 전달된 action, 과 payload, 처리 된 후의 상태등 시간에 따른 변화를 볼 수 없다. Redux Devtools 을 이용하면 시간에 따른 상태 차이를 볼 수 있다.
    • useReducer 는 미들웨어가 없다.

    ✨결론!

    해결하려는 문제에 가장 적합한 도구를 선택하자!

     

    ✅ 단순 prop-drilling 을 피하는 것이 목적이라면 Context 를 사용한다.

    ✅ 적당히 복잡한 컴포넌트가 있거나 외부 라이브러리를 사용하고 싶지 않다면 Context + useReducer를 사용한다.

    ✅ 특정 구성 요소만 re-render 시키거나, 사이드 이펙트를 줄이기 위해 더 강력한 기능이 필요하다면 Redux + React-Redux를 사용한다.

     

    https://velog.io/@dae_eun2/Context-API-와-Redux-비교

     

    Context API 와 Redux 비교

    일반적인 React에서 props 전달 흐름은 탑-다운 으로 진행된다.전달 되는 prop이 많아지고 컴포넌트 깊이가 깊어지면 관리가 번거로워 질 수 있다.Context Tree는 컨텍스트 안에 포함된 모든 레벨에서

    velog.io

    https://delivan.dev/react/stop-asking-if-react-hooks-replace-redux-kr/

     

    [번역] React Hooks가 Redux를 대체할 수 있냐고 물어보지 마세요

    이 글은 Max González가 작성한 Stop Asking if React Hooks Replace Redux를 번역한 글입니다. 글을 그대로 직역하기 보다는 좀 더 전달이 명확할 것 같다고 생각한 뉘앙스를 첨가하여 번역을 진행했습니다.

    delivan.dev

     

    728x90

    'React' 카테고리의 다른 글

    모달창 외부 클릭 시 모달 닫기  (0) 2023.07.30
    리액트에서 애니메이션 효과 구현하기  (0) 2023.07.26
    Jest  (0) 2022.11.10
    TDD  (0) 2022.11.10
    React project 복사하기  (0) 2022.11.10

    댓글