본문 바로가기

스폰지밥으로 공부하는 swift/객체지향과 디자인패턴

빌 프린터로 알아보는 Observer 패턴

728x90

 

공식문서에서는 '등록된 참관인에게 정보를 방송할 수 있는 알림 발송 메커니즘입니다.' 라고 되어있는데요.. 잘 와닿지는 않죠?

 

쉽게 풀어 설명해보겠습니다.


집게리아에서는 손님들이 주문을 하면 그 주문이 징징이를 거쳐 스펀지밥에게 전달되는데요, 징징이가 주문을 받은 후 스펀지밥한테 어떤 주문이 들어왔는지 소리치면 스펀지밥은 조리를 시작하죠. 하지만 이런 방식은 징징이에게 많은 부담을 주고, 스펀지밥도 주문을 놓칠 수 있는 리스크가 있어요.

 

이 문제를 해결하기 위해 집게리아는 '빌 프린터'를 도입하기로 합니다. 징징이가 주문을 받으면 이 프린터를 통해 주문 내용이 바로 주방에 전달되는 시스템이에요.


이제 징징이는 주문을 큰 소리로 외칠 필요가 없고, 손님들은 식사에 집중할 수 있겠네요! 그리고 스펀지밥은 주문서를 확인하고 바로 조리를 시작할 수 있어요. 여기서 주문서 프린트는 바로 '이벤트'가 되는 셈이고, 주방의 스펀지밥은 이 이벤트에 반응하는 '옵저버'가 되죠.

집게사장도 여분의 프린터를 가지고있다면(구독을 한 상태) 주문이 들어올 때마다 어떤 주문이 들어왔는지 확인을 할 수 있어요.

 

 

 

 

 

옵저버 패턴은 이처럼 특정 이벤트가 발생했을 때 해당 이벤트에 관심이 있는 객체들에게 알림을 보내주는 패턴입니다 :)

class Squidward {
    func receiveOrder(order: String) {
        print("징징이가 주문을 받았습니다: \(order)")
        NotificationCenter.default.post(name: NSNotification.Name("NewOrder"), object: nil, userInfo: ["order": order])
    }
}

class SpongeBob {
    init() {
        NotificationCenter.default.addObserver(self, selector: #selector(handleOrder(notification:)), name: NSNotification.Name("NewOrder"), object: nil)
    }

    @objc func handleOrder(notification: Notification) {
        if let order = notification.userInfo?["order"] as? String {
            print("스펀지밥이 \(order) 주문을 받아 조리를 시작합니다.")
        }
    }
}

class MrKrabs {
    init() {
        NotificationCenter.default.addObserver(self, selector: #selector(handleOrder(notification:)), name: NSNotification.Name("NewOrder"), object: nil)
    }

    @objc func handleOrder(notification: Notification) {
        if let order = notification.userInfo?["order"] as? String {
            print("집게사장이 \(order) 주문을 확인합니다.")
        }
    }
}

// 사용 예시
let squidward = Squidward()
let spongeBob = SpongeBob() // 스펀지밥이 주문 알림을 기다림
let mrKrabs = MrKrabs() // 집게사장도 주문 알림을 기다림

squidward.receiveOrder(order: "크랩버거") // 징징이가 주문을 받고 조리부와 집게사장에게 알림을 보냄

 

왜 @objc 써야함?

objc에서 객체의 생성과 소멸, 메모리 관리, 객체 간의 비교 같은 기본적인 작업을 수행할 수 있게 해주는 NSObject의 상속을 받기 때문입니다!

didset과 차이는 뭐지?

didSet은 프로퍼티 옵저버의 일종으로, Swift에서 제공하는 기능인데요, 프로퍼티의 값이 새로운 값으로 설정될 때마다 호출되는 코드 블록을 정의할 수 있죠. didSet은 주로 단일 객체 내에서 프로퍼티의 변경을 감지하고 반응할 때 사용됩니다. 예를 들어 사용자 인터페이스의 특정 요소를 업데이트하거나, 다른 변수의 값을 계산할 때 유용하게 사용되요.

그래서 didSet은 그 사용이 해당 프로퍼티에 한정되기 때문에 간단한 상황에서 상태 변화에 반응하는 데 적합합니다.

RxSwift나 Combine 등 선언형 프레임워크는 대부분 Observer 패턴으로 구현되어있는데요, 이번 포스팅이 옵저버 패턴을 이해하는데 도움이 되었으면 좋겠네요 :) 

이해가 가시지 않거나 설명이 더 필요한 부분 있다면 댓글로 남겨주세요!