Python 옵저버 패턴

Python 옵저버 패턴

DesignPattern
Python 옵저버 패턴
Author

gabriel yang

Published

November 25, 2024


옵저버 패턴(Observer Pattern) 이해하기

소프트웨어 개발에서 객체 간의 상호작용을 효율적으로 관리하는 것은 중요한 설계 과제 중 하나입니다. 이런 문제를 해결하기 위해 사용되는 디자인 패턴 중 하나가 바로 옵저버 패턴(Observer Pattern)입니다. 이번 글에서는 옵저버 패턴의 개념과 필요성, 그리고 Python 코드를 활용한 실제 구현 예제를 소개합니다.

1. 옵저버 패턴이란?

옵저버 패턴은 객체의 상태 변화를 관찰하고, 그 변화를 다른 객체들에게 자동으로 알리는 디자인 패턴입니다. 이 패턴을 통해 주체(Subject)옵저버(Observer) 간의 느슨한 결합(Loose Coupling)을 유지할 수 있습니다.

핵심 개념

  1. 주체(Subject)
    • 상태를 관리하며, 옵저버들에게 상태 변화 이벤트를 알리는 역할을 합니다.
  2. 옵저버(Observer)
    • 주체의 상태를 구독하고, 상태가 변경되었을 때 알림을 받아 필요한 작업을 수행합니다.

2. 왜 옵저버 패턴을 사용해야 할까?

  1. 객체 간의 결합도를 낮춤 옵저버 패턴을 사용하면 객체 간의 의존성을 낮추고 확장성을 높일 수 있습니다. 예를 들어, 주체는 옵저버가 몇 개인지 또는 어떤 작업을 수행하는지 알 필요가 없습니다.

  2. 상태 변화에 대한 자동 반응 주체의 상태가 변경되었을 때, 모든 구독자(옵저버)에게 자동으로 알림을 보내므로 수동으로 알림을 관리하지 않아도 됩니다.

3. 옵저버 패턴을 사용해야 하는 경우

  1. 객체 상태의 변경 사항을 다른 객체들에게 알릴 필요가 있을 때
    • 예: 데이터 모델이 변경되었을 때 UI를 업데이트하는 경우.
  2. 여러 객체가 동일한 주체의 상태를 구독해야 할 때
    • 예: 채팅 애플리케이션에서 새로운 메시지를 모든 사용자에게 알리는 경우.

4. Python으로 옵저버 패턴 구현하기

예제: 뉴스 구독 시스템

from abc import ABC, abstractmethod
from typing import List

# 1. 옵저버 인터페이스 정의
class Observer(ABC):
    @abstractmethod
    def update(self, message: str) -> None:
        pass

# 2. 주체 클래스 정의
class NewsPublisher:
    def __init__(self):
        self._subscribers: List[Observer] = []  # 구독자 리스트

    def subscribe(self, observer: Observer) -> None:
        self._subscribers.append(observer)

    def unsubscribe(self, observer: Observer) -> None:
        self._subscribers.remove(observer)

    def notify(self, message: str) -> None:
        for subscriber in self._subscribers:
            subscriber.update(message)

# 3. 구체적인 옵저버 구현
class EmailSubscriber(Observer):
    def __init__(self, email: str):
        self.email = email

    def update(self, message: str) -> None:
        print(f"Email to {self.email}: {message}")

class SMSSubscriber(Observer):
    def __init__(self, phone_number: str):
        self.phone_number = phone_number

    def update(self, message: str) -> None:
        print(f"SMS to {self.phone_number}: {message}")

class AppNotificationSubscriber(Observer):
    def __init__(self, username: str):
        self.username = username

    def update(self, message: str) -> None:
        print(f"App Notification to {self.username}: {message}")

# 4. 옵저버 패턴 사용 예시
if __name__ == "__main__":
    # 주체 생성
    publisher = NewsPublisher()

    # 구독자 생성
    email_subscriber = EmailSubscriber("user@example.com")
    sms_subscriber = SMSSubscriber("010-1234-5678")
    app_subscriber = AppNotificationSubscriber("user123")

    # 구독자 등록
    publisher.subscribe(email_subscriber)
    publisher.subscribe(sms_subscriber)
    publisher.subscribe(app_subscriber)

    # 상태 변경 알림
    publisher.notify("Breaking News: Design patterns are awesome!")

    # 구독 해제
    publisher.unsubscribe(sms_subscriber)

    # 상태 변경 알림
    publisher.notify("Update: Observer pattern explained!")

5. 코드 설명

  1. 옵저버 인터페이스 (Observer)
    • 모든 구독자는 update 메서드를 구현해야 합니다.
    • 상태 변경 시 주체가 호출하여 알림을 전달합니다.
  2. 주체 (NewsPublisher)
    • _subscribers 리스트를 통해 옵저버들을 관리합니다.
    • subscribeunsubscribe 메서드로 옵저버를 추가하거나 제거합니다.
    • notify 메서드를 통해 모든 구독자에게 메시지를 알립니다.
  3. 구체적인 옵저버 (EmailSubscriber, SMSSubscriber, AppNotificationSubscriber)
    • 각각 이메일, SMS, 앱 알림을 처리하는 구독자 클래스입니다.
  4. 패턴 사용 예시
    • 뉴스 알림 시스템에서 구독자를 추가/제거하고, 주체 상태 변경 시 자동으로 메시지를 전송합니다.

6. 실행 결과

Email to user@example.com: Breaking News: Design patterns are awesome!
SMS to 010-1234-5678: Breaking News: Design patterns are awesome!
App Notification to user123: Breaking News: Design patterns are awesome!

Email to user@example.com: Update: Observer pattern explained!
App Notification to user123: Update: Observer pattern explained!
  • 첫 번째 알림은 모든 구독자에게 전달됩니다.
  • 두 번째 알림에서는 SMS 구독자가 제거되었으므로, 나머지 두 구독자에게만 전달됩니다.

7. 옵저버 패턴의 장점

  1. 느슨한 결합 주체와 옵저버 간의 의존성이 낮아 확장성과 재사용성이 높습니다.

  2. 자동화된 알림 주체 상태 변경 시 수동으로 알림을 관리할 필요가 없습니다.

  3. 유연성 런타임에 옵저버를 추가하거나 제거할 수 있습니다.

8. 옵저버 패턴의 단점

  1. 복잡도 증가 주체와 옵저버가 많아지면 시스템이 복잡해질 수 있습니다.

  2. 디버깅 어려움 옵저버 간의 의존 관계가 복잡한 경우, 디버깅이 어려울 수 있습니다.

마무리

옵저버 패턴은 객체 상태의 변경을 여러 객체에게 자동으로 알리기 위한 강력한 도구입니다. 뉴스 구독 시스템과 같은 실제 사례를 통해 이 패턴의 유용성을 확인해보았습니다.

옵저버 패턴은 특히 이벤트 기반 시스템이나 실시간 알림이 필요한 애플리케이션에서 매우 유용합니다.