라떼군 이야기


3 / 13강

옵서버: 바뀐 내용을 구독자에게 알리기

재고가 바뀌면 화면과 기록 장치에 알려야 합니다. 재고 객체 안에 모든 화면 종류를 적어 두는 대신, 알림받을 함수를 등록하도록 만들 수 있습니다. 이것이 옵서버 패턴의 기본 발상입니다.

등록, 통지, 해제

class Stock:
    def __init__(self):
        self.quantity = 0
        self.listeners = []
    def subscribe(self, listener):
        self.listeners.append(listener)
    def unsubscribe(self, listener):
        self.listeners.remove(listener)
    def set_quantity(self, quantity):
        self.quantity = quantity
        for listener in list(self.listeners):
            listener(quantity)

def show(quantity):
    print("stock:", quantity)

stock = Stock()
stock.subscribe(show)
stock.set_quantity(3)
stock.unsubscribe(show)
stock.set_quantity(2)

출력은 stock: 3 한 번입니다. 구독을 해제한 뒤 바꾼 재고 2는 출력하지 않습니다. 통지할 때 목록을 복사하므로, 콜백이 구독 목록을 바꾸어도 현재 순회의 대상이 갑자기 달라지지 않습니다.

알림 정책도 설계의 일부입니다

예제는 등록 순서대로 같은 실행 흐름에서 콜백을 부릅니다. 옵서버라고 자동으로 비동기 처리되는 것은 아닙니다. 한 구독자가 느리거나 오류를 내면 다른 구독자에게도 영향을 줄 수 있습니다. 오류를 전파할지, 개별적으로 기록하고 계속할지 정책을 정해야 합니다.

화면이 사라질 때 구독을 해제하지 않으면 필요 없는 객체가 남거나 중복 알림을 받을 수 있습니다. 반대로 알림을 받은 쪽이 다시 값을 바꾸면 반복 통지가 생길 수 있습니다.

확인 문제

같은 화면을 열 때마다 콜백을 새로 등록했는데 닫을 때 해제하지 않았습니다. 어떤 증상이 생길 수 있을까요?

해설 보기

한 번의 변경에 같은 동작이 여러 번 실행되거나 닫힌 화면이 계속 참조될 수 있습니다. 구독을 시작한 곳과 끝내는 곳을 짝지어 관리해야 합니다.

제품 기획, 개발 파트너 찾으시나요? 개인, 팀, 기업 모두 환영. 문제 정의부터 출시까지 함께합니다.