옵저버 패턴이란?
옵저버 (관찰자)들이 관찰하고 있는 대상자의 상태가 변화가 있을 때마다 대상자는 직접 목록의 각 관찰자들에게 통지하고, 관찰자들은 알림을 받아 조치를 취하는 행동 패턴이다.
옵저버 패턴은 일대다(one-to-many) 의존성을 가지고, 주로 분산 이벤트 핸들링 시스템을 구현하는데 사용된다.
다른 말로는 (발행/구독) 모델이라고도 부른다.
일상 생활에서 찾아보면 유튜브로 비유할 수 있다.
유튜브에는 유튜버 채널은 발행자가 되고 구독자들은 관찰자로 볼 수 있다.
구독자들이 채널 알림 설정을 해 놓으면 영상이 올라올 때 마다 알림을 받을 수 있는데, 이를 패턴 구조로 들여다 보면
구독자들은 해당 채널을 구독함으로써 채널에 어떠한 변화(영상을 올라왔을때)가 생기게 되면 알림을 받아
영상이 올라왔다는 것을 인지할 수 있다.
해당 비유를 아래 코드로 옮겨 적을 수 있다.
interface Subscriber {
fun update(videoTitle: String)
}
// YouTube Channel 클래스 (Subject)
class YouTubeChannel {
private val subscribers = mutableListOf<Subscriber>()
var latestVideoTitle: String = ""
fun subscribe(subscriber: Subscriber) {
subscribers.add(subscriber)
}
fun unsubscribe(subscriber: Subscriber) {
subscribers.remove(subscriber)
}
fun notifySubscribers() {
for (subscriber in subscribers) {
subscriber.update(latestVideoTitle)
}
}
fun uploadVideo(title: String) {
latestVideoTitle = title
println("Uploading video: $title")
notifySubscribers()
}
}
// 구독자 클래스 (Concrete Observer)
class ConcreteSubscriber(private val name: String) : Subscriber {
override fun update(videoTitle: String) {
println("$name received notification: New video uploaded - $videoTitle")
}
}
fun main() {
val channel = YouTubeChannel()
val subscriber1 = ConcreteSubscriber("Subscriber 1")
val subscriber2 = ConcreteSubscriber("Subscriber 2")
channel.subscribe(subscriber1)
channel.subscribe(subscriber2)
channel.uploadVideo("Kotlin Observer Pattern Tutorial")
channel.unsubscribe(subscriber1)
channel.uploadVideo("Advanced Kotlin Features")
}
옵저버 패턴는 언제 사용될까요?
- 사용자 인터페이스(UI) 요소가 백엔드에서 데이터를 받아와 화면에 반영해야할 때
- 사용자의 입력, 시스템 이벤트, 네트워크 메시지 등과 같은 이벤트를 처리할 때
- MVC 아키텍처에서 모델의 상태가 변하면 이를 뷰에게 알려야 할 때
옵저버 패턴의 주요 구성 요소
1.Subject (발행자, 유튜버 채널)
- 상태가 변할 수 있는 객체이다.
- 옵저버들 관리(추가, 제거)한다.
- 상태 변화가 발생하면 등록된 모든 옵저버에게 알림을 보낸다.
2. 옵저버 (관찰자, 구독자)
- 구독하고 있는 채널의 상태(영상 업로드, 게시글 작성)가 변하면 반응하는 객체이다.
- 주제로부터 알림을 받을 때 특정 행동을 수행한다.
옵저버 패턴의 장점과 단점
옵저버 패턴 장점
- 관찰자와 구독자는 서로 독립적으로 동작한다.
- 발행자는 관찰자가 구체적으로 어떤 작업을 하는지 알 필요가 없으며, 반대로 관찰자는 발행자의 내부 구현을
알 필요가 없다. - 발행자의 상태 변경을 주기적으로 조회하지 않고 자동으로 감지할 수 있다.
- 발행자의 코드를 변경하지 않고 새 관찰자 클래스를 도입할 수 있어 개방 폐쇄 원칙을 준수한다.
- 런타임 시점에서 발행자와 구독 알림 관계를 맺을 수 있다.
옵저버 패턴 단점
- 발행자가 관찰자에 대한 참조를 계속 유지를 하고 있으면 관찰자가 필요 없어진 후에도 메모리가 해제되지 않아
메모리 누수가 발생할 수 있다. - 많은 수의 관찰자가 있을 때, 각각에게 알림 보내는것은 비효율적일 수 도 있다. (옵저버의 오버헤드)