이번 편은 전역 상태 관리(Global State Management) 모듈의 최고봉인 redux에 대한 내용이 담겨 있었다. 그런데, 내용에 물음표가 조금 붙더라. 교재의 골자는 prop drilling의 문제와 그 해법으로 전역 상태 관리를 이용하는 것인데, 이미 이 앞 편에서 Context API를 다뤘기 때문이다. 그러므로, 흐름 상 Context API와 redux를 비교해야 자연스럽다.
여기에는 이유가 있다. 이 책은 저자의 리액트 관련 비정기 동영상 강의를 활자로 만들어 엮은 것이었다. 그러다 보니, 모든 파트가 커리큘럼으로 묶이지 않고, 몇몇 토픽들을 독립적으로 다루고 있다. 파트 사이의 연결고리가 없고 필요 지식은 별도로 습득해야 하기 때문에(예를 들어 redux를 따로 공부하고 이 번 편을 봐야 함), 냉정하게 이야기하자면 이 책만 가지고 초심자가 독학하여 일정 수준에 이르기에는 무리가 있다.
교재의 내용과는 별도로 Context API와 redux를 비교해 보려고 한다.
먼저, Context API를 이용해 prop drilling이 없는 코드를 짜보았다.
import { createContext, useContext, useState } from 'react'; const css = ` div { border-radius: 3px; border: 3px solid gray; margin: 10px; padding: 10px; } `; const ColorCtx = createContext(); function Top1() { return ( <div> <h3>Top1</h3> <Top2/> </div> ); } function Top2() { return ( <div> <h3>Top2</h3> <Top3/> </div> ); } function Top3() { const { color, setColor } = useContext(ColorCtx); return ( <div> <h3 style={{ 'color': color }} onClick={() => color === 'black' ? setColor('green') : setColor('black')}>Top3</h3> </div> ); } function Bottom1() { return ( <div> <h3>Bottom1</h3> <Bottom2/> </div> ); } function Bottom2() { return ( <div> <h3>Bottom2</h3> <Bottom3/> </div> ); } function Bottom3() { const { color, setColor } = useContext(ColorCtx); return ( <div> <h3 style={{ 'color': color }} onClick={() => color === 'black' ? setColor('green') : setColor('black')}>Bottom3</h3> </div> ); } function App() { const [color, setColor] = useState('black'); return ( <ColorCtx.Provider value={{ color, setColor }}> <style>{css}</style> <Top1/> <Bottom1/> </ColorCtx.Provider> ); } export default App;
위 예제는 아래와 같은 뎁스의 박스를 그리고, Top3나 Bottom3를 클릭하면 글자색이 바뀌도록 동작한다.


위 그림처럼 Top3/Bottom3 어떤 것을 클릭해도 글자색이 함께 바뀌는 걸 볼 수 있다.
예제를 좀 더 자세히 설명하겠다. context는 그냥 전역 값 공유만 하기 때문에 컴포넌트 리렌더링을 발생시키려면 state(또는 reducer)와 같이 써야 한다. 그런데, state는 컴포넌트 내에만 존재할 수 있으니, 최상위 컴포넌트를 글로벌 영역으로 추정해야 한다. 그 후 context에 state를 담아 컴포넌트 체인으로 내려 보내면 최상위 이하 모든 컴포넌트가 해당 state를 공유할 수 있다. 상용 레벨에서도 많이 쓰이는 기법이다.
context + state(reducer)가 상용 레벨에서 많이 쓰인다고 해도 공식 전역 관리자(Zustand, Redux, Jotai, Recoil 등등)를 대체할 수는 없다. 일단, context에 state를 담아 내려보내면 state가 바뀔 때마다 모든 컴포넌트가 리렌더링 되므로, 변경이 잦은 state를 이렇게 사용하면 성능에 심각한 영향을 끼친다. 그리고, 구조화나 편의기능 제공 등 모든 면에서 열세이므로 react 기본 모듈만을 사용하면 생산성이 많이 떨어질 것이다.
이런 연유로 초기 진입장벽이 있더라도 처음부터 전역 상태 관리자를 이용하는 것이 필요하다. 위 코드를 redux를 이용하는 것으로 최대한 비슷하게 바꿔 보았다.
import React from 'react'; import { createStore } from 'redux'; import { Provider, useDispatch, useSelector } from 'react-redux'; const css = ` div { border-radius: 3px; border: 3px solid gray; margin: 10px; padding: 10px; } `; const initialState = { color: 'black' }; function colorReducer(state = initialState, action) { const newState = { ...state, color: action.type === 'green' ? 'green' : 'black' }; return newState; } const store = createStore(colorReducer); function Top1() { return ( <div> <h3>Top1</h3> <Top2 /> </div> ); } function Top2() { return ( <div> <h3>Top2</h3> <Top3 /> </div> ); } function Top3() { const color = useSelector(state => state.color); const dispatch = useDispatch(); return ( <div> <h3 style={{ color }} onClick={() => dispatch({type: color === 'black' ? 'green' : 'black'})}> Top3 </h3> </div> ); } function Bottom1() { return ( <div> <h3>Bottom1</h3> <Bottom2 /> </div> ); } function Bottom2() { return ( <div> <h3>Bottom2</h3> <Bottom3 /> </div> ); } function Bottom3() { const color = useSelector(state => state.color); const dispatch = useDispatch(); return ( <div> <h3 style={{ color }} onClick={() => dispatch({type: color === 'black' ? 'green' : 'black'})}> Bottom3 </h3> </div> ); } function App() { return ( <Provider store={store}> <style>{css}</style> <Top1 /> <Bottom1 /> </Provider> ); } export default App;
간단한 코드라도 막상 바꿔보니 더 나아 보인다.
공부를 하다보니, 순수 redux는 거의 쓰지 않고 redux toolkit(RTK)를 쓴다고 하는데, 마침 다음 편이 RTK를 다루는 거라 기대가 된다.
'Book Study > 생활코딩! React 리액트 프로그래밍' 카테고리의 다른 글
15일차 Next.js - 생활코딩! React 리액트 프로그래밍 (終) (0) | 2025.04.02 |
---|---|
14일차 리덕스 툴킷 - 생활코딩! React 리액트 프로그래밍 (0) | 2025.03.31 |
12일차 useReducer - 생활코딩! React 리액트 프로그래밍 (0) | 2025.03.28 |
11일차 Context API - 생활코딩! React 리액트 프로그래밍 (0) | 2025.03.27 |
10일차 스타일드 컴포넌트 - 생활코딩! React 리액트 프로그래밍 (0) | 2025.03.24 |