본문 바로가기

개발/JavaScript

[Javascript] Observer Pattern 옵저버 패턴

옵저버 패턴(Observer pattern)이란?

한 객체의 상태가 바뀌면 그 객체에 의존하는 다른 객체들한테 연락이 가고 자동으로 내용이 갱신되는 일대다(one to many) 의존성을 갖는 패턴을 의미한다.

 

주로 출판사와 구독자에 비유를 한다. 

출판사 = 주제(Subject), 구독자 = 옵저버(Observer)에 비유를 하며, 구독자는 출판사에게 구독 신청, 구독 취소를 하고  구독중엔 변경된 내용을 전달 받는다.

 

- 옵저버는 주제에 의존한다.

- 주제(Subject)객체의 데이터가 달라지면 옵저버한테 2가 전달된다.

- 옵저버 객체들은 주제 객체를 구독하고 있으며(등록하고 있으며) 주제의 데이터가 바뀌면 갱신 내용을 전달받는다.

 

옵저버의 특징

- 느슨한 결합(Loose coupling)이다.

느슨한 결합이란?

두 객체가 상호작용을 하긴 하지만 서로에 대해 잘 모른다는 것을 의미한다. (객체 사이의 상호의존성을 최소화) 그래서 옵저버를 언제든지 새로 추가하고 삭제할 수 있으며 주제나 옵저버가 바뀌어도 서로에게 영향을 미치지 않는다는 장점이 있다.

 

 

JS로 구현

심플하게 옵저버 패턴을 구현하였다.

class Subject {
    constructor() {
      this.observers = [];
    }
    
    // 옵저버 등록(구독)
    subscribe(observer) {
      this.observers.push(observer);
    }

    // 옵저버 제거(구독취소)
    unsubscribe(observer) {
      this.observers.splice(this.observers.indexOf(observer), 1);
    }
    
    // 변경을 알려주는 함수
    notifyAll(data) {
      this.observers.forEach(observer => observer(data)); 
    //  함수로 넣었을 때
    //  this.observers.forEach((observer) => observer.notify(state));
    }
  }
  
  const subject = new Subject();
  
  const observer1 = data => console.log('first ' + data);
  const observer2 = data => console.log('second ' + data);
  
//  객체가 아닌 함수로 넣었을 때.
//  const observer1 = { notify : (str) => console.log("first " + str) };
//  const observer2 = { notify : (str) => console.log("second " + str) }; 
 
  subject.subscribe(observer1); // 구독
  subject.subscribe(observer2); // 구독
  subject.notifyAll("abc1");
  
  subject.unsubscribe(observer2); // 구독 취소
  subject.notifyAll("abc2");

 

결과 화면

first abs1
second abc1
first abc2

 

JS에서의 사용

Vue나 React 같은 프레임워크의 주된 목적 중 하나가 상태를 기반으로 DOM을 렌더링하는데 Vanila JS로 상태관리 시스템을 구현할 때 옵저버 패턴이 사용된다. 그것또한 나중에 공부해서 추가하고 수정 할 예정이다.

 

 


Reference

Headfirst 디자인패턴 책