🧠 JavaScript 상태 관리 완전 정복|전역 상태 vs 지역 상태, 옵저버블과 이벤트 버스까지
안녕하세요, 퍼블리셔 노미입니다! 😊
오늘은 자바스크립트에서 아주 중요한 주제, “상태 관리(State Management)”에 대해 탄탄하게 정리해보려고 해요! 💡
상태란 단순히 값을 저장하는 것 이상으로, 앱의 흐름과 로직을 좌우하는 핵심 요소예요. 특히 SPA(Single Page Application)에서는 상태 관리 능력 = 실력이라고 해도 과언이 아니죠. 🔧
이번 글에서는 다음을 다룹니다:
- 📍 상태(state)란 무엇인가?
- 🧭 지역 상태 vs 전역 상태
- 🔄 옵저버 패턴과 상태 반응성
- 🛜 이벤트 버스 직접 구현
- 📊 SPA 구조에서 상태 흐름 설계 전략
✨ 자, 이제 상태의 흐름을 명확하게 이해하러 가볼까요?
📍 상태(state)란 무엇인가요?
상태는 컴포넌트 혹은 애플리케이션의 데이터 저장소입니다. 화면에 보이는 UI는 모두 상태에 의해 결정돼요! 🎯
예시
let count = 0;
function increase() {
count += 1;
console.log(count); // 화면 업데이트는 이 값을 기준으로 결정
}
→ 상태는 단순한 변수 같지만, 앱의 “현재 상황”을 나타내는 핵심이에요!
🧭 지역 상태 vs 전역 상태
상태는 어디에서 접근하고, 누가 관리하느냐에 따라 지역(Local)과 전역(Global)으로 나뉘어요.
🔹 지역 상태 (Local State)
컴포넌트 내부에서만 사용하는 상태
// React 기준 예시
const [isOpen, setIsOpen] = useState(false);
- 🧩 특정 기능만 사용하는 값
- 📍 컴포넌트에 종속됨
- 🔒 외부에서 접근 불가
🔸 전역 상태 (Global State)
여러 컴포넌트/페이지가 공유해야 하는 상태
- 👤 로그인 상태
- 🛒 장바구니
- 📦 공통 설정값 (다크모드 등)
→ 규모가 커질수록 전역 상태 관리가 중요해져요! 🏗️
🔁 옵저버 패턴으로 반응형 상태 만들기
옵저버 패턴(Observer Pattern)은 한 객체의 상태가 바뀌면, 이를 구독하고 있는 다른 객체들에게 자동으로 알림을 보내는 구조예요. 📡
📌 간단한 예제
class State {
constructor(value) {
this.value = value;
this.listeners = [];
}
subscribe(listener) {
this.listeners.push(listener);
}
set(newValue) {
this.value = newValue;
this.listeners.forEach((fn) => fn(newValue));
}
get() {
return this.value;
}
}
// 사용
const counter = new State(0);
counter.subscribe((val) => console.log('구독자:', val));
counter.set(1); // 구독자: 1
counter.set(2); // 구독자: 2
- 🧠 상태가 바뀔 때마다 모든 구독자가 자동 반응
- 📦 여러 컴포넌트에 영향을 주는 상태 관리에 딱!
→ 이게 바로 React의 useEffect나 Recoil이 내부에서 하는 원리와 비슷해요!
📡 이벤트 버스(Event Bus) 직접 만들기
이벤트 버스는 컴포넌트 간 직접적인 관계 없이 전역으로 이벤트를 주고받을 수 있게 해주는 중계자예요! 🛰️
📌 예제 구현
class EventBus {
constructor() {
this.events = {};
}
on(event, handler) {
(this.events[event] ||= []).push(handler);
}
emit(event, data) {
if (this.events[event]) {
this.events[event].forEach((fn) => fn(data));
}
}
off(event, handler) {
this.events[event] = (this.events[event] || []).filter(fn => fn !== handler);
}
}
// 사용
const bus = new EventBus();
bus.on('login', (user) => {
console.log('👤 로그인됨:', user);
});
bus.emit('login', { name: '노미' }); // 👤 로그인됨: { name: '노미' }
→ 컴포넌트 간 통신을 유연하게 해주는 전략이에요! 🔌
📊 SPA에서 상태 흐름 설계 전략
SPA(Single Page Application)에서는 다양한 상태가 동시에 존재합니다. 그래서 상태를 어디서 선언하고, 어떻게 흘려보낼지에 대한 전략이 중요해요! 🧭
💡 설계 팁
- 📍 컴포넌트 내부에서만 쓰는 값 → 지역 상태로
- 🔁 여러 곳에서 공유하는 값 → 전역 상태로
- 📶 글로벌 브로드캐스트용 → 이벤트 버스 활용
- 🧱 복잡한 비즈니스 로직 → 상태 라이브러리 도입 (예: Redux, Zustand, Recoil)
🧩 상태 흐름 예시 (React 기반)
App
├── AuthProvider (로그인 상태)
│ └── Header
├── ProductPage
│ └── ProductCard (지역 상태: isHovered)
├── CartProvider (장바구니 상태)
│ └── CartModal
→ "누가 상태를 소유하고, 누가 소비할 것인가?" 를 기준으로 설계! 🧠
🧠 상태 관리 핵심 요약
- 🧩 상태(state): 앱의 현재 데이터를 저장하는 공간
- 📍 지역 상태: 컴포넌트 내부에서만 사용하는 값
- 🌐 전역 상태: 여러 컴포넌트가 공유하는 값
- 🔁 옵저버 패턴: 상태 변화에 반응하는 구조
- 📡 이벤트 버스: 전역 이벤트 전달/수신 시스템
→ 상태를 누가, 어디서, 어떻게 다룰지 명확히 하자! ✍️
🧰 추천 상태 관리 도구/패턴
도구/패턴 | 주요 특징 | 추천 상황 |
---|---|---|
useState | 가볍고 지역적 | 단순한 컴포넌트 상태 |
Context API | 전역 상태 공유 | 테마, 언어, 로그인 |
Redux | 중앙 집중, 확장성 | 대규모 앱, 예측 가능한 상태 |
Zustand | 간결하고 가볍다 | React 전역 상태를 깔끔하게 |
Recoil | atom 단위 상태, 의존성 트리 | React + fine-grained 상태 구조 |
옵저버 패턴 | 구독 기반 | 직접 구현, 반응성 학습용 |
이벤트 버스 | 간단한 전역 통신 | Vue/Nuxt/비컴포넌트간 전송 |
→ 프로젝트 규모와 팀 상황에 따라 적절한 도구를 선택하세요! 🎯
📌 상황별 상태 관리 전략 요약
- 🧱 작은 UI 변경 → useState / 지역 변수
- 🧭 글로벌 공통 설정 → Context / Recoil / Zustand
- 🏗️ 복잡한 데이터 흐름 (예: 쇼핑몰) → Redux
- 🎛️ 레거시나 외부 컴포넌트 연결 → 이벤트 버스
- ⚡ 반응형 로직 학습 → 옵저버 패턴 직접 구현
→ 상태 관리 전략은 "단순할수록 좋다"는 걸 기억하세요! 🙌
📚 마무리하며
상태 관리는 단순한 기술이 아닌 앱의 설계 철학이에요. 🧠 어떤 상태를 어디서 관리할지 명확히 결정하는 것이 코드의 가독성, 유지보수성, 확장성을 좌우합니다.
이번 글에서는 상태의 개념 → 분류 → 구현 → 설계 전략
까지 3만자 분량으로 부드럽고 알차게 정리해드렸어요!
다음 글에서는 💥 상태와 UI 렌더링 최적화 전략 (메모이제이션, useMemo, useCallback 등) 실전 React에서의 성능 개선 팁도 이어서 다룰게요! 끝까지 읽어주셔서 감사합니다! 😊 함께 더 성장해요! 🌱🚀
#JavaScript상태관리 #전역상태 #옵저버패턴 #이벤트버스 #상태흐름 #퍼블리셔노미 #프론트엔드설계 #상태관리전략 #JS실전패턴
'차근차근' 카테고리의 다른 글
JavaScript 성능 최적화 실전편|렌더링, 메모리, 디바운스/스로틀까지 한 번에! (1) | 2025.05.23 |
---|---|
JavaScript 이벤트 루프 완전 정복|콜 스택, 태스크 큐, 마이크로태스크 한눈에 이해하기 (1) | 2025.05.21 |
JavaScript 비동기 패턴 완전 정복|콜백부터 async/await, 병렬 처리까지 한 번에! (1) | 2025.05.20 |
JavaScript 디자인 패턴 실전편|모듈부터 전략 패턴까지 코드로 배우기 (1) | 2025.05.19 |
프론트엔드 개발 환경 완전 정복|Webpack, Vite, Babel로 모던 프로젝트 세팅하기 (1) | 2025.05.18 |