Don't give up!

[Design Pattern] 옵저버 패턴(Observer Pattern)과 발행-구독 패턴(Publisher-Subscriber Pattern) 본문

개발서적/Head First Design Patterns

[Design Pattern] 옵저버 패턴(Observer Pattern)과 발행-구독 패턴(Publisher-Subscriber Pattern)

Heang Lee 2021. 8. 28. 21:28
이 글은 에릭 프리먼의 'Head First Design Patterns'를 읽고 TIL(Today I Learned)로써 공부한 내용을 기록하는 글입니다.
자세한 내용은 책을 통해 확인하실 수 있습니다.

알라딘: Head First Design Patterns (aladin.co.kr)

 

Head First Design Patterns

볼 거리가 많고 재미있으면서도, 머리 속에 쏙쏙 들어오는 방식으로 구성된 Head First 시리즈. 패턴의 근간이 되는 객체지향 디자인 원칙, 중요한 패턴, 디자인 적용 방법, 쓰지 말아야 하는 이유

www.aladin.co.kr

옵저버 패턴(Observer Pattern)

옵저버 패턴은 주제와 옵저버사이의 일대다 관계를 정의합니다.

주제의 상태가 바뀌면 그 객체에 의존하는 다른 객체인 옵저버들에게 연락을 전달하고 자동으로 내용을 갱신합니다.

옵저버 패턴에서 주제와 옵저버는 느슨한 결합을 유지합니다.

옵저버 패턴은 주제와 옵저버를 인터페이스로 일반화합니다.

주제 역할을 하는 클래스, 옵저버 역할을 하는 클래스는 각각 Subject, Observer 인터페이스를 구현하기만 하면 되므로 옵저버의 구상 클래스가 무엇인지, 옵저버가 무엇을 하는지 등에 대해서 알 필요가 없습니다.

각 클래스가 서로에 대해 잘 모르기 때문에 주제와 옵저버는 서로 독립적이며 재사용가능합니다.

옵저버 패턴은 Subject가 모든 Observer들에게 변화를 알려주는 Push 방식, Observer들이 Subject에게 데이터를 요청하는 Pull방식을 사용하여 적용할 수 있습니다.

자바 내장 옵저버 패턴

자바는 java.util 패키지 내부의 Observable 클래스와 Observer 인터페이스로 옵저버 패턴을 지원하였습니다.

Observable (Java SE 10 & JDK 10 ) (oracle.com)

 

Observable (Java SE 10 & JDK 10 )

This class represents an observable object, or "data" in the model-view paradigm. It can be subclassed to represent an object that the application wants to have observed. An observable object can have one or more observers. An observer may be any object th

docs.oracle.com

'지원하였습니다'라고 표현한 이유는 Observable과 Observer는 JDK 9부터 deprecated되었기 때문입니다.

기존의 Observable 클래스가 갖는 문제는 다음과 같습니다.

  1. Observable은 인터페이스가 아닌 클래스기 때문에 서브클래스를 만들어야 하고, 다른 슈퍼 클래스를 확장하고 있는 클래스에 Observable 기능을 추가할 수 없었습니다. (Observable을 상속받는 클래스는 다중 상속 문제에 의해 Serializable을 상속받을 수 없습니다.)
  2. Observable은 Thread-Safe 하지 않습니다. 느슨한 결합을 이루고 있기 때문에 특정 연락 순서에 의존하지 않습니다. 이는 다른 쓰레드에서 실행된 결과가 다를 수 있음을 의미합니다.
  3. Observable 클래스의 setChanged() 메소드가 protected로 선언되어 있어 이를 상속받는 서브 클래스에서만 호출할 수 있습니다. 

발행-구독 패턴(Publisher-Subscriber Pattern)

옵저버 패턴의 Subject와 Observer 사이의 관계, 발행-구독 패턴의 Publisher와 Subscriber 사이의 관계는 유사합니다.

Subject와 Publisher가 Observer와 Subscriber에게 변화를 알려주는 관계를 형성하고 있습니다.

그러나 두 패턴은 같지 않습니다.

발행-구독 패턴에서 Publisher와 Subscriber 사이에는 브로커(Broker) 혹은 이벤트 버스(Event Bus)로 불리는 계층이 존재합니다.

출처 : Publish/Subscribe Microsoft Docs

발행-구독 패턴은 Publisher가 Subscriber의 위치나 존재를 알 필요 없이 브로커에게 메시지를 던져놓기만 하면 되며 반대로 Subscriber 역시 브로커에 할당된 작업만 모니터링하다 작업하면 되므로 옵저버 패턴에 비해 결합도가 더 낮습니다.

또한 발행-구독 패턴은 브로커라는 중간 매개체가 있기 때문에 도메인이 다르더라도 브로커에 접근할 수 있다면 처리할 수 있다는 점이 다른 점입니다.

스프링에서의 옵저버 패턴

스프링은 Event에 옵저버 패턴을 적용하고 있습니다.

SpringApplication의 ApplicationContextFactory는 AbstractApplicationContext를 상속받는 AnnotationConfigApplicationContext를 create함수로 반환하는데, 이 AbstractApplicationContext에서 Event를 담당하는 ApplicationEventMulticaster와 has-a 관계를 갖고 있습니다.

AbstractApplicationContext의 initApplicationEventMulticaster() 메소드

ApplicationEventMulticaster는 인터페이스입니다.

addApplicationListener, removeApplicationListener의 메소드를 통해 ApplicationListener를 등록/삭제하고 multicastEvent로 이벤트에 적절한 리스너를 찾아 등록합니다.

ApplicationEventMulticaster 인터페이스