티스토리 뷰

React :

Context API란


https://velopert.com/3606 참고해서, 조금더 내용을 보강하여 리덕스와의 비교를 통해 느낀점을 보태 정리한 내용입니다.


| 시작하기에 앞서


3월말에 리액트 16.3 이 정식 릴리즈가 되고 기존에 존재하던 Context API 가 새로워졌습니다. 이렇게, 새로워진 Context API 에 대해서, 한번 자세히 다뤄볼것입니다.


| Context의 용도


  • 주로, 애플리케이션으로 전역적으로 데이터가 사용되야 할 때 사용됩니다. 기존의 Context API 도 전역적으로 데이터를 관리하는 용도로 사용할 수는 있었지만, 사용성이 조금 불편해서 자주 사용되지는 않았다고 합니다. 
  • 주로, redux, react-router, styled-components 등이 기존에 이 Context API 를 기반으로 구현이 되어있다고 합니다. Context API 가 이번에, 단순히 그런 라이브러리에서 사용되는 용도가 아니라, 일반적인 용도로도 사용하기 용이하게끔 업그레이드 되었다고 합니다.


| Context 생성


createContext 함수를 호출하면 Provider 와 Consumer 라는 컴포넌트들이 반환됩니다. Provider 는 Context 에서 사용 할 값을 설정할 때 사용되고, Consumer 는 나중에 우리가 설정한 값을 불러와야 할 때 사용됩니다.


참고로, Context 여러개를 만들 수가 있습니다. 때문에, 여러개의 Context 사용 이름이 겹치지 않고 쉽게 다루기 위해서 위와 같이 Provider Consumer 앞에 prefix 설정해주기도 한다고 합니다.

const { Provider, Consumer: SampleConsumer } = Context;

// Provider 에서 state 를 사용하기 위해서 컴포넌트를 새로 만들어줍니다.
class SampleProvider extends Component {
 state = {
   value: "기본값입니다"
};

> Provider


현재 컴포넌트의 state actions 객체를 넣은 객체를 만들어서,Provider value 값으로 사용합니다.


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

Context 를 프로젝트에 적용하려면, 앱을 Provider 로 감싸주어야합니다. App.js 를 다음과 같이 수정해야합니다.

const App = () => {
 return (
   <SampleProvider>
     <div className="panes">
       <LeftPane />
       <RightPane />
     </div>
   </SampleProvider>
);
};

export default App;

이는 리덕스에서 provider로 감싸주는것과 유사한것 같았습니다. 여기서 리덕스의 구현체가 Context API라는것도 느낄수 있었습니다.


Consumer


아래와 같이, Consumer를 통해 Context 의 값을 가져올수 있습니다. 


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

const Receives = () => {
 return (
   <SampleConsumer>
    {
      (sample) => (
         <div>
          현재 설정된 값: { sample.state.value }
         </div>
      )
    }
   </SampleConsumer>
);
};

export default Receives;

  • 따라서 아래와 같이 활용해 볼 수 있습니다. 기존에 context를 만들때 만들었던, actions 를 통해서 값을 변경할 수 있습니다.이는 리덕스에서의 액션생성함수에 디스패치 해주는 형태와 유사한점을 알수 있었습니다.
  • 또한 Context API의 Consumer 역시, Redux에서 HOC 형태인 connect를 사용해 mapStateToProps mapDispatchToProps를 사용해서 액션생성함수를 가져오거나 Redux state를 가져오는 패턴과 유사하다는 점에서 Context API의 패턴을 차용한점도 느낄 수 있었습니다.


import React, { Component } from 'react';
import { SampleConsumer } from '../contexts/sample';

class Sends extends Component {

 state = {
   input: ''
}

 componentDidMount() {
   // :: 초기 값 설정
   this.setState({
     input: this.props.value,
  })
}
 
 handleChange = (e) => {
   this.setState({ input: e.target.value });
}

 handleSubmit = (e) => {
   e.preventDefault();
   // :: props로 받은 setValue 호출
   this.props.setValue(this.state.input);
}

 render() {
   return (
     <form onSubmit={this.handleSubmit}>
       <input value={this.state.input} onChange={this.handleChange}/>
       <button type="submit">설정</button>
     </form>
  );
}
}

// :: Consumer 를 사용하여 context 값을 전달해준 컨테이너 컴포넌트
const SendsContainer = () => (
 <SampleConsumer>
  {
    ({state, actions}) => (
       <Sends
         value={state.value}
         setValue={actions.setValue}
       />
    )
  }
 </SampleConsumer>
)

// :: Sends 대신에 SendsContainer 를 내보내줌
export default SendsContainer;

| 느낀점

간단한 실습을 해보면서 Context API 는 글로벌 상태관리를 조금 더 쉽게 해준다는 것은 사실인 것 같았습니다. 조금더 자유롭게 코드를 짤수도 있구요. 그래서 기존에 단순히, 복잡하게 depth가 깊어지는 컴포넌트 구조에서 데이터 전달하는 용도로만 리덕스를 사용했더라면 리덕스를 대체 할 수는 있겠다는 생각은 들었습니다. 하지만, 리덕스는 단순한 전역적 상태 관리 뿐아니라, 액션기반 앱 상태 업데이트 로직 작성부터 시작해서, 리덕스 saga나, react-router 등등의 미들웨어와 같이 사용되고, Redux dev tool 등등을 사용할수 있는 점은 큰 차이점이라는 생각이 들었습니다.


댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
TAG
more
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함