Share
Sign In

옵저버 패턴, PubSub 패턴

옵저버 패턴

옵저버 패턴은 1:N 관계가 있을 때, 한 객체의 상태가 변경되면 모든 종속 객체가 자동으로 알림을 받고 업데이트 되도록 하는 패턴이다. 이 패턴은 단일 객체에 대한 변경 사항을 알려야 하는 여러 객체가 있을 때 유용하다.
단 발행자와 수신자가 긴밀하게 커플링되어 있다. 때문에 로직 변경에 신경써야 한다.
class Subject { constructor() { this.observers = []; } subscribe(observer) { this.observers.push(observer); } unsubscribe(observer) { this.observers = this.observers.filter(o => o !== observer); } notify() { this.observers.forEach(observer => observer.update()); } } class Observer { constructor(name) { this.name = name; } update() { console.log(`${this.name} 이 메시지를 받았습니다.`); } } const subject = new Subject(); const observer1 = new Observer('bob'); const observer2 = new Observer('alex'); subject.subscribe(observer1); subject.subscribe(observer2); subject.notify(); subject.unsubscribe(observer1); subject.notify();

Pub-Sub 패턴

Pub-Sub 패턴은, 옵저버 패턴과 개념은 유사하지만, N:N 관계에 사용할 수 있다. 중간에 메시지 브로커가 있고, 특정 토픽을 변경하면 그 토픽을 구독하고 있는 모든 구독자에게 메시지를 보내는 형태이다. 따라서 발행자와 구독자는 서로가 누구인지 알 필요가 없고, 이 때문에 서로 디커플링을 유지하기 쉽다.
다음 예제를 보자.
class MessageBroker { constructor() { this.subscriptions = new Map(); } subscribe(topic, subscriber) { let subscribers = this.subscriptions.get(topic); if (!subscribers) { subscribers = new Set(); this.subscriptions.set(topic, subscribers); } subscribers.add(subscriber); } unsubscribe(topic, subscriber) { const subscribers = this.subscriptions.get(topic); if (subscribers) { subscribers.delete(subscriber); if (subscribers.size === 0) { this.subscriptions.delete(topic); } } } publish(topic, message) { const subscribers = this.subscriptions.get(topic); if (subscribers) { subscribers.forEach(subscriber => { subscriber.receive(topic, message); }); } } } class Subscriber { receive(topic, message) { throw new Error('receive 로직 구현이 필요합니다.') } } class User extends Subscriber { constructor(name) { this.name = name; } receive(topic, message) { console.log(`${this.name} 님이 메시지를 받았습니다. ${topic}: ${message}`); } } const messageBroker = new MessageBroker(); const gameSubscriber = new User('bob'); const techSubscriber = new User('alex'); messageBroker.subscribe('game', gameSubscriber); messageBroker.subscribe('tech', techSubscriber); messageBroker.publish('game', '피파온라인5 출시'); messageBroker.publish('tech', 'gpt5 출시');