Observer, Store

이수정·2025년 9월 8일

JS_웹_풀스택

목록 보기
5/12

Observer Pattern

  • 목적 : 모듈간의 의존성을 낮춤 === 결합도를 낮춤
  • 관찰 대상의 상태 변화가 있을 때마다 대상자는 관찰자들에게 통지, 관찰자들은 알림을 받아 조치를 취하는 행동패턴
  • 일대다 의존성 -> 분산 이벤트 핸들링 시스템 구현
  • 대상 객체의 상태 변경될 때마다 다른 객체 동작 트리거
  • MVC 패턴에서도 사용 [Model, View, Controller]
    - Model-View ==> Subject-Observer 관계 대응
    • 이벤트 -> 상태 변경(Model-Observable) -> View-Observer
  • 구독 & 발행
    ex ) 신문사(발행)가 신문을 독자(구독 리스트)에게 배달(구독)
    ex ) Issue List 상태가 변경되면 list와 count를 Observer로 지정하여 업데이트 가능

다음과 같은 역할이 필요하다.

  • 구독 방법
  • 구독 리스트
  • 이벤트 발행
class Observable { //!== rxJS Observable
    constructor() {
        this._observers = new Set();
    }
    subscribe(observer) {
        this._observers.add(observer);
    }
    unsubscribe(observer) {
        this._observers.delete(observer);
    }
    notify(data) {
        this._observers.forEach(observer => observer(data));
    }
}

observer는 subscribe 메서드를 통해 this._observers(구독 리스트)에 추가
-> 이벤트 발생 시 notify

패턴 구조

관찰 대상 : ConcreteSubject
구독자 : Observer A, B

  • ISubject : 관찰 대상을 정의하는 인터페이스
  • IObserver : 구독자 묶는 인터페이스

=> 합성한 객체를 리스트로 관리, 리스트 객체에게 모두 메서드 위임을 통한 전파

Observer Pattern 참고

Observable-Observe

  • Observable : observe에서 사용
  • Observable(=> 상태)에 변화가 생기면 observe(구독 리스트)에 등록된 함수 실행

Object.defineProperty

: 객체에 새로운 속성을 정의하거나 이미 존재하는 속성을 수정하여 객체 반환

Object.defineProperty(object, prop, descriptor)

  • object 속성을 정의할 객체
  • prop 새로 정의하거나 수정하려는 속성의 이름 또는 Symbol
  • descriptor 새로 정의하거나 수정하려는 속성을 기술하는 객체

Store

현대 FE 개발에서 상태관리 중요성 대두
Vue / React : 상태를 기반으로 DOM을 렌더링
but. component 깊이가 깊어져 상태관리 복잡 => Store(중앙 집중식 저장소)

Store-Component

  • Store : 여러 컴포넌트에서 사용 가능
  • Store 변경시 구독한 Component도 변경
// Store를 생성한다.
const store = new Store({
  a: 10,
  b: 20,
});

// 컴포넌트를 생성한다.
const component1 = new Component({ subscribe: [store] });
const component2 = new Component({ subscribe: [store] });

// 컴포넌트가 store를 구독한다.
component1.subscribe(store); // a + b = ${store.state.a + store.state.b}
component2.subscribe(store); // a * b = ${store.state.a * store.state.b}

// store의 state를 변경한다.
store.setState({
  a: 100,
  b: 200,
});

// store가 변경되었음을 알린다.
store.notify();
  • Observer 패턴으로 작성
const store = {
    state: { issueState: "open" },
    listeners: [],

    setState(patch) {
        // TODO: state 갱신 후 notify 호출
        this.state = { ...this.state, ...patch };
        this.notify(this.state);
    },

    subscribe(fn) {
        // TODO: 구독자 등록
        this.listeners.push(fn);
    },

    notify() {
        // TODO: 모든 구독자에게 state 전달
        this.listeners.forEach(fn => fn(this.state));
    }
};

// ---- View 객체 ----
const TextView = {
    init() {
        // TODO: store에 구독 등록
        store.subscribe(this.render.bind(this));
    },

    render(state) {
        if (state.issueState === "open") {
            console.log("현재 상태는 OPEN 입니다.");
        } else {
            console.log("현재 상태는 CLOSED 입니다.");
        }
    }
};

// ---- Menu 뷰 객체 (완성된 코드임) ----
const Menu = {
    open() {
        store.setState({ issueState: "open" });
    },
    close() {
        store.setState({ issueState: "closed" });
    }
};
// ---- 연결 ----
TextView.init();

// ---- 실행 예시 ----
//Menu.close();
//Menu.open();

Store 참고

0개의 댓글