개념/배경

한 객체의 상태 변화나 이벤트를 여러 객체가 자동으로 감지하고 반응하게 만드는 구조를 Observer 패턴이라 부름 발행자와 구독자의 관계로도 설명됨. Publisher가 이벤트를 내보내고 Subscribers가 이를 받는 흐름 핵심은 느슨한 결합과 자동 알림 흐름 유지

핵심 개념과 구성요소

  • Subject 또는 Observable
    • 이벤트를 발생시키는 주체
    • Observer 목록을 관리
    • 상태가 변하면 observers에 알림 전파
  • Observer
    • 상태 변화를 알고 싶은 소비자
    • update 같은 콜백 보유
  • notify
    • Subject가 모든 Observer에게 브로드캐스트하는 동작

동작 원리

  • Observer가 Subject에 구독 등록
  • Subject 상태 변화 발생
  • Subject가 notify 실행, 등록된 Observer의 콜백 호출
  • Observer는 전달된 값에 따라 자체 로직 수행

필수 인터페이스의 최소 형태는 아래와 같음

// 핵심 메서드 형태만 발췌
interface Observer {
  update(value: unknown): void
}

// Subject는 내부에 observers 보유
// subscribe, unsubscribe, notify 동작 제공
// notify(value) -> 모든 observer.update(value)

왜 쓰는가

  • 하나의 변화에 여러 객체가 반응해야 하는 요구 충족
    • 예: 버튼 클릭 한 번에 여러 UI 혹은 모듈 업데이트 필요
  • 느슨한 결합 유지
    • Subject는 Observer의 구체 타입이나 구현을 모를 수 있음
  • 이벤트 기반 비동기 흐름 표현에 적합
    • UI 이벤트, 도메인 이벤트, 시스템 시그널 등 다양한 케이스에 적용 가능

RxJS와의 관계

RxJS는 Observer 패턴을 비동기 스트림 개념으로 확장한 라이브러리

  • Observer는 next, error, complete 세 가지 콜백으로 구성
  • Subject는 내부적으로 Observer 목록을 관리하고 next 호출 시 모든 구독자에 브로드캐스트
  • 구독과 해제, 리소스 정리와 같은 수명주기 관리 포함

요소 매핑 관점에서 보면 다음과 같은 대응 관계를 가짐

  • Subject ↔ Observable 또는 Subject
  • Observer ↔ next/error/complete 콜백을 가진 객체
  • notify ↔ next 호출
  • 구독 관계 ↔ subscribe 호출

즉, RxJS는 기본 Observer 패턴에 연속 데이터 스트림, 비동기 처리, 구독 해제와 정리 같은 운영 요소를 더해 실무 활용도를 높인 형태

주의와 한계

  • 메모리 누수 리스크
    • 구독 해제 누락 시 Observer가 참조 유지되어 GC가 불가해질 수 있음. unsubscribe 또는 구독 관리 유틸 사용 권장
  • 호출 순서와 동기성
    • 단순 구현은 동기 브로드캐스트가 기본. 비동기 순서 보장은 별도 설계 필요
  • 에러 처리와 전파
    • 기본 Observer 패턴에는 표준화된 에러 전파 방식 부재. RxJS는 error, complete로 보완
  • Pub/Sub와의 관계
    • 개념적으로 유사. Observer는 객체 간 직접 참조가 전제되는 경우가 많고, Pub/Sub는 브로커를 두어 간접 라우팅하는 경우가 많음. 구현 선택은 시스템 결합도와 배포 토폴로지에 따라 결정

간단 예시

// 최소한의 흐름만 표현
subject.subscribe(observer)
subject.notify(10) // 내부적으로 observer.update(10)

마무리

Observer 패턴은 한 객체의 이벤트를 여러 객체가 자동으로 구독하고 반응하는 구조 제공 RxJS는 이를 비동기 스트림으로 확장해 연속 데이터, 에러 처리, 구독 해제까지 포함하는 실용적 모델 제공

참고자료