Redux vs Context API

Happhee·2022년 3월 14일
0

💙  React 💙

목록 보기
8/18

앞에서 Redux를 공부하면서 React만 사용할 수 있는 상태관리 도구인 Context API에 대한 궁금증이 생겨서 이 글을 작성하게 되었다.

Context API와 Redux를 비교하면서 개념을 확실히 정리해보자


✨ Context API란?

중앙 상태 관리를 위한 상태 관리 도구이다.

React에서 Props와 State는 부모 컴포넌트와 자식 컴포넌트 또는 한 컴포넌트 안에서 데이터를 다루기 위해 사용한다고 했다. 하지만, 부모 컴포넌트로부터 자식 컴포넌트로 전달되는 데이터의 흐름과는 관계없이 전역적인 데이터를 다룰 때 필요한 것이다.

이를 위해서 React는 Flux라는 개념을 도입하고, 그에 맞는 Context API를 제공하기 시작했다.

Redux와는 달리,
Context API에서는 여러 저장소가 존재할 수 있으며, Context, Provider, Consumer로 나뉘어진다.


✨ Context API의 흐름

Context

전역 상태가 저장되는 곳이다.

전역 데이터를 Context에 저장하고, Context안에는 Provider와 Consumer가 정의되어 있다.
다른 컴포넌트에서는 이를 활용하여 상태에 접근할 수 있다.

여러 개의 Context가 사용될 수 있고, 만약 단 하나의 Context만 존재한다면 성능상의 문제가 발생할 수 있으므로 주의해야 한다.

React.createContext

import React from 'react';

export default React.createContext(defaultValue);

React.createContext()의 인자로 상태의 초기값이 들어간다. 즉, initState와 같은 기능을 한다.
defaultValue는 적절한 Provider를 찾지 못했을 때, 사용되는 값이다.

만약, provider를 통해서 undefined를 보낸다고 해도 해당 context를 가진 컴포넌트는 provider를 읽지 못한다.


Provider

정의한 Context를 하위 컴포넌트에 전달하는 역할을 한다.

  • Provider를 전달하는 변수는 꼭 value를 사용해야 한다.
  • 전달 받는 컴포넌트의 제한은 없다.

제공된 상태에 접근하기 위해서는 Provider의 하위 컴포넌트에 포함되어 있어야 한다.

따라서 모든 컴포넌트에 접근하는 상태를 제공하는 루트 컴포넌트가 필요하므로, index.js 또는 app.js에서 Provider를 정의해야 하는 것을 지켜야 한다.

Context.Provider

//React.createContext()객체
import UserContext from './userContext';

class App extends Component {
  render(){
    return(
      <UserContext.Provider value={{
      name :'',
      age : 0
      }}>
      	{/*여기서 전역상태에 접근가능*/}
	</UserContext.Provider>
}

Consumer

Context의 변화를 구독하는 컴포넌트이다.

  • context의 자식은 컴포넌트이어야 한다.
  • 해당 컴포넌트가 가지는 context값은 가장 가까운 provider의 값이며, 상위 provider가 존재하지 않을 경우에는 defaultValue를 갖는다.

Context.Consumer

<UserContext.Consumer>
  {value => /* context값을 이용한 렌더링*/}
</UserContext.Consumer>

Context는 Cousumer 사이에 있는 처음의 객체를 Context에 인자로 전달하기 때문에, 바로 JSX를 작성하는 것이 아니라 빈 객체를 작성한 뒤 JSX 객체를 작성해야 한다.


간단한 예제

createContext + Consumer

  • Profile.js
import { createContext } from 'react';

const ProfileContext = createContext({ name : "seohee", age : 12});

export default ProfileContext;

context를 생성하면서 기본으로 프로필의 정보를 지정해주었다.
이후, consumer를 사용하여 ProfileContext 안에 있는 정보를 조회할 수 있다.

  • ProfileBox.js
import React from 'react';
import ProfileContext from '../Contexts/Profile';

const ProfileBox = () => {
  return(
    <ProfileContext.Consumer>
    {(value)=> (
    	<div style={{width : "64px", height: "64px"}}>
    		<div> NAME : {value.name}</div>
			<div> AGE : {value.age}</div>
    	</div>
    )}
    </ProfileContext>
);
}
export default ProfileBox;

최종적으로 App에서 이를 실행해주면 된다.

  • App.js
import React from 'react';
import ProfileBox from './ProfileBox';

const App = () =>{
  return (
    <div>
    	<ProfileBox/>
    </div>
    );
};

export default App;

Provider 사용

App.js에 provider를 추가하여 ProfileBox의 이름과 나이를 변경할 수 있다,

import React from 'react';
import ProfileBox from './ProfileBox';
import ProfileContext from './Profile';

const App = () => {
  return(
    <ProfileContext.Provider value={{name : "SEOHEE", age: 24}}>
    <div>
    	<ProfileBox/>
    </div>
);
};
export default App;

동적 Context 사용

context의 value에는 값이 아닌 함수도 사용이 가능하다.

  • Profile.js
import { createContext, useState } from 'react';
import React from 'react';

const ProfileContext = createContext({
  state : { name : "seohee", age : 12},
  actions : {
    setName : () => {},
    setAge : () => {},
  }
});

const ProfileProvider = ({children}) => {
  const [name, setName] = useState("SEOHEE");
  const [age, setAge] = useState(24);
  const value = {
    state : { name,age},
    actions : { setName, setAge}
  };
  
  return (
    <ProfileContext.Provider value = {value}>
    {children}
	</ProfileContext.Provider>
);
};

const { Consumer : ProfileConsumer } = ProfileContext;

export { ProfileProvider, ProfileConsumer};
  • ProfileBox.js
import React from 'react';
import { ProfileConsumer } from './Profile';

const ProfileBox = () => {
  return (
  	<ProfileConsumer >
    {({state}) => (
  		<div style={{width:'64px', height:'64px'}}>
    		<div> NAME : {value.name}</div>
			<div> AGE : {value.age}</div>
    	</div>
  	)}
    </ProfileConsumer>
  )
};
export default ProfileBox;

✨ Redux vs Context API 차이점

예제를 살펴보았듯이 Redux와 Context API는 전역 상태 관리를 위한 도구라는 것을 알 수 있으며, Redux가 Context API를 가지고 만든 라이브러리라는 사실 또한 알아낼 수 있다.

하지만, Redux는 Context API와는 다르게 전역 상태 관리 외에도 다양한 기능을 제공한다.
해당 기능은 아래와 같다.👇

  • 로컬 스토리지에 상태를 영구적으로 저장하고, 시작할 때 다시 불러오기가 가능하다.
  • 사용자의 액션을 상태와 함께 자동으로 기록할 수 있다.
    👉 버그 찾는데 용이하다.
  • 개발할 때의 상태 내역 사이를 오가는 것이 가능하기에, 액션 내역에서 현재 상태를 다시 계산하는 일을 TDD 스타일로 구현할 수 잇다.
  • 비즈니스 로직 대부분을 재사용하면서 UI를 변경할 수 있게 한다.

즉, Redux가 부가 기능을 많이 제공되어지고 있기에 이러한 기능이 필요하지 않고, 오로지 전역 상태 관리만을 필요로 한다면 Context API를 사용하면 된다.


📚 학습할 때, 참고한 자료 📚

profile
즐기면서 정확하게 나아가는 웹프론트엔드 개발자 https://happhee-dev.tistory.com/ 로 이전하였습니다

0개의 댓글