Context API

이대희·2021년 11월 13일

React에 대한 첫 의심이 드는 순간...

   React는 부모 컴퍼넌트로부터 자식 컴퍼넌트에게 Props를 전달하는 개별적 구조들의 집합체이다. 처음에는 이 구조가 신기하고 재미있게 느껴진다. 문제는 전달하는 단계가 많아질 수록, 재미는 반감되고 관리하기가 귀찮아 진다는 사실에 있다. 예를 들어 1단계 -> 2단계 -> 3단계 -> 4단계 의 구조를 가지는 컴퍼넌트가 있다고 하자. 1단계에서 state를 만들어서 4단계에서 사용하려면, 실질적으로 의미없는 3단계를 거쳐야 하는 문제를 마주하게 된다. 리액트에 대한 첫 의심과 함께 불필요하게 느껴지는 단계들을 생략하고, 4단계에서 바로 state들에 접근하고자 하는 욕구가 샘솟게 된다.
  아래 그림은 그 예시이다. 화살표 하나가 props로 전달하는 과정이라고 생각하면 된다. 구현하고자 하는 페이지의 복잡도가 증가할 수록 화살표의 갯수도 증가하게 될 것이다.

Context API

   그것을 위한 해결책으로 제시되는 것이 바로 전역적으로 state에 접근할 수 있도록 도와주는 Context API이다. 최상위 Context Component에 한 번만 선언을 하면, 이제는 각각의 개별 component 내에서 바로 원하는 state나 그 state를 변경할 수 있는 method에 접근할 수 있게 된다. 불필요한 코드 작성도 줄이고 각 component들을 관리하기도 수월해진다.

사용법

   ① Context 객체를 생성하기

const ContextInstance = React.createContext(초기값);

   ② Provider component 설정하기
  context의 변화를 알려줄 component가 필요한데, 그 역할을 provider component가 하게 된다.

<ContextInstance.Provider value={전달하고자 하는 state나 method}>
   {children}
</ContextInstance.Provider>

   ③ 각 컴퍼넌트에서 context의 state에 접근할 수 있도록 useContext 사용하기

export const useContextInstance = () => useContext(ContextInstance);

   ④ 각 컴포넌트에서 접근하기

const {사용하고자 하는 state나 method}= useContextInstance();
  • useContext는 각 컴포넌트에서 context에 접근하는 것을 도와주는 리액트 빌트인 hook이다. 여기서 따로 적지는 않았지만, Provider의 짝꿍은 Consumer라는 것을 기억할 것. 원래는 Consumer Component를 사용해서 Provider의 value에 접근하여서 사용한다. 아래는 conumer를 사용하는 방법이다.
<ContextInstance.Consumer>
  {value => /* context 값을 이용한 렌더링 */}
</ContextInstance.Consumer>

Context API는 만병통치약?

   그렇다면 모든 state들을 Context API로 관리하면 되는 걸까? context API는 결코 남발되어서는 안된다. 예를 들어 특정 input의 값을 저장하는 state를 수정한다고 가정해보자. 우리는 보통 이것을 onChange를 통해서 값이 변화할 때마다 state를 수정하는데, 이것은 context를 변화시키기 때문에, Provider를 구독하는 모든 Component들이 rerender되는 상황을 맞을 수 있다. 코드 작성 자체는 편할지도 모르지만, 사이트의 성능이 저하되는 문제를 가져오게 되는 것이다. 아래의 코드는 그 예시이다.

const MyComponent = ()=>{
 // context에서 불러오기
 const {inputData, setInputData}= useContextInstance();
 
 // input에서 값에 변화가 일어날 때마다 작동하는 함수
 // context의 변화로 인해 그 아래 모든 component들 rerender
 const onChange = (event)=>{
 	setInputData(event.target.value);
 }
 
 return (
 	<input value={inputData} onChange={onChange} />
 );
}

그렇다면 언제, 어떻게 Context API를 사용해야할까?

   이것은 사실 정답이라는 기준을 세울 수는 없겠지만, 사이트 전체에 영향을 줘야하는 것을 기준으로 삼는 방법이 있을 수 있다. 예를 들어, 로그인을 했는지 안했는지는 생각보다 중요한 이슈이다. 따라서 로그인여부는 Context API를 사용해도 상대적으로 괜찮을 수 있다. 또 다른 예시로는 야간모드 설정, 언어 설정 등이 있을 수 있다.

Context보다 합성은 어때?

   React 공식문서에서는 Context의 사용을 남발하기 보다는, Componenet들을 합성하는 것도 하나의 해결책으로 제시하고 있다. 합성은 state를 전달하는 것이 아니라 component 자체를 props로 전달하는 것이다(아래의 그림을 보자). 이렇게 사용할 경우, 중간 과정의 Component들은 어떤 state가 전달되어야 하는지 몰라도 된다. 그런데 rerender라는 이유를 제외하더라도, context의 대안으로 합성을 권장하는 이유가 있다. 그 이유는 바로 재사용성이다. Context로 모든 것을 처리하기 시작하면 component들을 재사용하기 어려워진다.

profile
코딩하는 사람

0개의 댓글