본문 바로가기

React/실험실

[React] Context API 언제 사용해야할까?

앞서 Context API에 대한 글을 몇개 작성했다. 

하지만 결국 Context API를 언제 사용해야 하는지 이런 부분에 대해서는 결론에 도달하지 못했다. 

 

Redux vs Context 는 정말 많은 이야기가 있지만 정작 어떤 경우에 어떤 것을 사용해야 좋을지 모른 상태에서 

그저 " 사용 " 하고 있었다. 

 

이번에는 근복적인 내용으로 Context와 Redux가 무엇이고 어떻게 사용해야하고, 어떻게 다른지, 언제 사용해야하는지 

결론을 정리하려고 한다. 

 

React Context란? 

일반적인 React 애플리케이션의 데이터는 위에서 아래로 Props를 통해서 전달되지만, 
애플리케이션 안의 여러 컴포넌트들에 전해줘야 하는 경우 번거로울 수 있다. 

context를 사용하면 트리 단계마다 명시적으로 props를 넘겨주지 않아도 많은 컴포넌트가 이러한 값을 
공유하도록 할 수 있다. 

React 공식 사이트에서 소개하는 Context이다. 

여기서도 값에 대한 "관리"는 언급하지 않고 값을 전달 및 공유에 대해서 언급하고 있다. 

 

즉, Context는 실제로 어떤 것도 관리하고 있지 않다는 것을 알 고 있다. 대신 파이프와 같은 역할을 하고 있다. 

결국 Context의 주된 목적은 Props Drilling을 방지하는 것이다. 

 

필요한 값을 명시적으로 Props를 통해 전달(Prop-passing)할 필요가 없기 때문에 코드가 단순해진다.  

 

개념적으로는 의존성 주입의 한 형태이다. 

자식 컴포넌트에서 특정한 상태값이 필요하다는 것은 알고 있지만 값 자체를 직접 생성하거나 설정하지 않고

상위 요소가 해당 값을 전달하고 있다. 

 

Redux란? 

Redux는 "액션"이라는 이벤트를 사용해서 애플리케이션 상태를 관리하고 업데이트 하기 위한
패턴 및 라이브러리이다.

상태가 예측 가능한 방식으로만 업데이트 될 수 있도록 하는 규칙과 함께 전체 애플리케이션에서 사용해야 하는 상태에 
대한 중앙 집중식 저장소 역할을 한다. 

Redux는 애플리케이션에서 여러 부분에서 필요한 상태인 "전역" 상태를 관리하는 데 도움이 된다. 
또한 언제, 어디서, 어떻게, 왜 업데이트가 되었는지 쉽게 이해할 수 있다. 

Redux 공식 사이트에서 소개하는 Redux이다. 

 

정리하면 Redux는 상태를 관리하며 상태 값의 변화를 쉽게 이해할 수 있다. 

 

Reducer 함수를 이용해서 상태 변경을 예측 가능하게 만들고, 사이드이펙트 및 저장소 확장 방법으로 미들웨어를

사용한다. 

또한 Redux Devtools를 이용해서 작업 기록 및 상태를 확인할 수 있다. 

 

Redux와 React 

Redux 자체는 UI에 구애받지 않는다. 모든 UI 레이어(React, Vue, Angular, etc )와 함께 사용할 수 있다. 

React-Redux 라이브러리는 Redux에서 상태 값을 읽고 action을 React 컴포넌트에게 전달하는 Redux 저장소와 

상호작용 할 수 있도록 도와주는 UI 바인딩 레이어이다. 

 

React-Redux를 사용하면 애플리케이션의 모든 React 요소들이 Redux 저장소에 접근이 가능한데, 

이는 React-Redux 내부에서 Context를 사용하기 때문이다. 

 

주의할 점은 React-Redux는 Context를 통해서 현재 상태 값을 전달하는 것이 아닌 

Redux 저장소 인스턴스를 전달한다. 

 

이것이 앞서 언급했던 의존성 주입을 위해 Context를 사용하는 예다. 

React 컴포넌트는 Redux의 저장소와 통신해야 하는 것은 알고 있지만 어떤 저장소와 통신을 해야하는지는 

신경쓰지 않는다. 

 

Redux에서 내부적으로 Context를 사용하기 때문에 prop-drilling을 피하기 위해서 사용할 수 있다. 

 

Redux의 목적과 사용 사례

React에서 Redux를 사용하는 많은 이유가 prop-drilling을 피하기 위해서 사용한다. 

그 외에도 Redux를 사용하는 이유로 다음과 같이 있다. 

UI 레이어 (React, Vue ... )와 분리된 상태 관리 로직을 작성하고 싶은 경우 

서로 다른 UI 레이어 간에 상태 관리 로직을 공유하는 경우 

작업을 진행할 때 Redux 미들웨어를 통해 추가적인 작업이 필요한 경우 

Redux 상태의 유지 

DevTool을 사용해서 버그 디버깅 

 

Context가 상태 관리가 아닌 이유 

상태 관리는 시간이 지남에 따라 상태가 변경되는 방식을 의미한다. 

 

다음과 같은 경우를 상태관리라고 한다. 

초기 값을 저장한다.

현재 값을 읽을 수 있다. 

값 업데이트가 가능하다. 

 

React의 useState와 useReducer가 이러한 예이다. 

Hook을 호출해서 초기 값 저장 

Hook을 호출해서 현재 값을 읽는다. 

제공된 setState 또는 dispatch 함수를 호출해서 값을 업데이트한다. 

구성 요소가 Re-Render 되었기 때문에 값이 업데이트 됐음을 알 수 있다. 

 

마찬가지로 Redux도 상태 관리이다. 

Root 리듀서를 호출해서 초기 값을 저장한다. 

store.getState()를 통해서 현재 값을 읽는다. 

store.dispatch를 통해서 업데이트 한다.

store.subscribe를 통해서 리스너에게 업데이트 되었음을 알린다. 

 

React의 Context는 위 조건을 충족하지 못하기 때문에 상태관리 도구라고 할 수 없다. 

Context는 그저 전달되는 값을 결정하는 역할을 하고 일반적으로 실제 상태 관리는 

useState / useReducer와 함께 발생하기 때문이다. 

 

다시 한번 말하지만 Context는 상태가 Context Tree 내부에 포함된 다른 컴포넌트들과 

공유되는 방식이다. 

 

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는 미들웨어가 없다. 

 

즉, Context + useReducer는 낮은 규모와 빈도의 업데이트와 같은 경우는 괜찮지만 

Flux와 유사한 상태 전파의 대체물로는 부족하다. 

 

불필요한 re-render를 줄이고 문제의 범위를 지정하기 위해서 개별 Context를 지정하고

React.memo, useMemo 등을 이용해서 코드를 작성하길 권장하지만 규모가 커진다면 결국 React-Redux를 

만드는 행위와 유사해진다. 

 

권장사항 

문제가 발생했을 때  가장 적합한 도구를 선택하는 것이 중요하다.

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

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

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

 

TL;DR

Context와 Redux는 같은 건가? 

아니다. Context와 Redux는 다른 툴이며, 다른 목적으로 사용된다. 

 

Context는 상태 관리 툴인가? 

아니다 Context는 의존성 주입(Dependency Injection)의 한 형태이다. 

그저 전송 메커니즘으로, 아무것도 관리하지 않는다. 상태 관리는 useState / useReducer 를 통해서 관리된다. 

 

그렇다면 Context와 useReducer는 Redux를 대처할 수 있는가? 

아니다. 물론 Context와 Redux는 유사한 점이나 겹치는 점은 있지만 핵심 기능은 다르다. 

 

언제 Context를 사용해야 할까?

단순하게 Props Drilling을 피하고 싶은 경우 

 

언제 Context와 useReducer를 사용해야 할까? 

애플리케이션에서 어느정도 복잡한 상태 관리가 필요한 경우 

 

그렇다면 언제 Redux를 사용해야 할까? 

▶ 여러 위치에서 많은 양의 상태가 있을 때 

▶ 업데이트 로직이 복잡한 경우 

▶ 큰 규모의 작업을 여러 사람과 함께 수행할 때 

▶ 상태가 언제, 왜, 어떻게 업데이트가 되었는지 이해하고, 상태 변경의 시각화를 희망할 경우 

▶ 사이드이펙트, 메모이제이션, 데이터 직렬화 등 관리를 위해 더 강력한 기능이 필요할 때 

 

출처 

https://blog.isquaredsoftware.com/2021/01/context-redux-differences/

 

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

Definitive answers and clarification on the purpose and use cases for Context and Redux

blog.isquaredsoftware.com

반응형

'React > 실험실' 카테고리의 다른 글

[React] Compound Component 패턴  (1) 2023.02.04
[React] Context Module Function 패턴  (0) 2023.02.02
[React] 독립된 React 컴포넌트의 이점  (0) 2023.01.29
[React] Suspense  (0) 2023.01.28
[React] Derived State  (0) 2023.01.25