본문 바로가기
차근차근

JavaScript 상태 관리 완전 정복|전역 상태 vs 지역 상태, 옵저버 패턴과 이벤트 버스까지

by 아빠고미 2025. 5. 22.
반응형

🧠 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실전패턴

반응형