전역 상태 관리
-Passing Data Deeply with Context 여러 컴포넌트에서 상태를 사용해야 할 때 === 전역 상태 관리가 필요할 때 사용할 수 있는 도구가 필요해짐
React의 상태를 관리하는 방법
내부
- useState
- Context API
외부
Props Drilling
🔄 용어 매핑
source → state owner / source of truth (상태가 처음 선언되고 보관되는 곳)
reader → consumer (상태를 props/context로 읽기만 하는 컴포넌트)
writer → updater / dispatcher (상태를 변경하는 setState 호출자)
bridge → intermediate / middle component (스스로 쓰진 않고 단순히 props를 전달만 하는 중간 다리 역할)
App → state owner (source of truth)
Child3 → consumer
Child6 → updater
Child2 → intermediate (중간 전달자)
- app에서 counter 상태를 만들고 관리한다.
- 1을 거쳐서 3까지 상태를 내려주고 상태를 띄운다
- 상태를 변경하는 경우 2를 거쳐 6까지 상태를 내려주고 상태 변경 함수를 적어주고 상태를 변경한다.
- 그리고 리렌더링 되어야하는 부분은 3에서만 일어나면 되지만, 지금 상태에서는 모든 컴포넌트가 다 리렌더링이 발생하고 있다. 즉, 불필요한 리렌더링이 발생하고 있다. 상태를 관리하는 app이 리렌더링 되고 있는 것
bash
📦 props-drilling-demo
└─ src
├─ App.jsx # 상태 선언, 트리 구성 (counter, setCounter)
└─ App.styled.js # 역할(role)별 색상/테두리 스타일scss
🧩 Component Tree (with roles & props)
App [$role=source]
└─ Outer
├─ Legend
└─ Container [$role=source]
└─ Component [$role=source] "Props Drilling"
├─ Child1 (props: counter) [$role=reader]
│ └─ Component [$role=reader]
│ ├─ Child3 (props: counter) [$role=reader] -> 화면에 counter 표시
│ └─ Child4 [-] -> 상태 미사용
└─ Child2 (props: counter, setCounter) [$role=bridge] -> 중계자
└─ Component [$role=bridge]
├─ Child5 [-] -> 상태 미사용
└─ Child6 (props: counter, setCounter)[$role=writer] -> 버튼 클릭 시 +1
🧩 Component Tree (roles & received props)
App [$role=source] (state: counter, setCounter)
└─ Outer
├─ Legend
└─ Container [$role=source]
└─ Component [$role=source] "Props Drilling"
├─ Child1 (props: counter) [$role=reader]
│ └─ Component [$role=reader] "Child1"
│ └─ Container
│ ├─ Child3 (props: counter) [$role=reader] → 화면에 표시
│ │ └─ Component [$role=reader] "Child3 : {counter}"
│ └─ Child4 (no props) [-]
│ └─ Component "Child4"
└─ Child2 (props: counter, setCounter) [$role=bridge]
└─ Component [$role=bridge] "Child2"
└─ Container
├─ Child5 (no props) [-]
│ └─ Component "Child5"
└─ Child6 (props: counter, setCounter) [$role=writer]
└─ Component [$role=writer] "Child6"
└─ button onClick → setCounter(counter + 1)diff
🔁 Data/Action Flow
STATE OUT (↓)
- counter: App → Child1 → Child3 | App → Child2 → Child6
- setCounter: App ───────────────→ Child2 → Child6
ACTION UP (↑)
- onClick in Child6 → setCounter(counter + 1) → App re-render
→ 읽는 컴포넌트(Child1/Child3)와 쓰는 컴포넌트(Child6)가 함께 업데이트css
🎨 Role Legend (styled-components)
source : bg #192524, border #3AA097, text #E6E7EB → 상태의 출발점
reader : bg #1B1C2A, border #7E86F9, text #E6E7EB → 읽기 전용 표시
bridge : bg #262015, border #DCAB70, text #E6E7EB → 중간 전달(직접 사용 X)
writer : bg #26181B, border #F291A0, text #E6E7EB → 상태 변경 주체
🎨 Role Legend (styled-components)
source → 상태의 출발점 : bg #192524, border #3AA097
reader → 읽기 전용 소비자 : bg #1B1C2A, border #7E86F9
bridge → 중간 전달자 : bg #262015, border #DCAB70
writer → 상태 변경 주체 : bg #26181B, border #F291A0
🔁 Data Flow (down) / Action Flow (up)
counter ↓ : App
→ Child1 → Child3 (표시)
→ Child2 → Child6 (버튼에 현재 값 전달)
setCounter ↓ : App
→ Child2 → Child6
onClick ↑ : Child6
→ setCounter(counter + 1) → App 재렌더
→ Child1/Child3(Reader)와 Child6(Writer) 업데이트diff
📌 Key Takeaways
- Props Drilling: 필요 없는 중간(bridge)까지 props가 통과해야 함.
- Reader/Writer 분리: Child3는 읽기만, Child6는 쓰기 전용.
- 개선 포인트: Context/상태관리 라이브러리로 bridge 제거 가능.
📌 핵심 포인트
- Props Drilling 데모: Child2는 직접 쓰지 않지만 props를 ‘전달’만 하는 bridge.
- Reader/Writer 분리: Child3는 읽기만, Child6는 쓰기만 담당.
- 개선 여지: Context/전역 상태로 bridge 경로를 제거 가능.Context API
사용법
- createContext로 전역 상태 만들기
- Provider로 전역 상태 연결해 주기
- useContext로 전역 상태 가져와 주기