Observer 패턴과 Pubsub 패턴에 대해서

puka·2023년 10월 21일

Pubsub이란

publish/subscribe의 줄임말이며, 비동기식 메세징 패턴입니다.

위와 같은 그림을 설명하자면

  1. 이벤트(메시지)를 발행하는 Publisher가 존재하며, Publisher는 특정 Channel(혹은 Topic)에 이벤트 전송한다.
  2. Publisher는 Subscriber를 모른체로 이벤트 발생 시 Event Channel에게 메세지를 넘겨준다.
  3. Subscriber는 Channel(혹은 Topic)을 구독하게 된다.
  4. 중간 컴포넌트는 이벤트들을 필터링해서 받아야 할 수신자들에게 보내준다.

여기서 pubsub의 하나의 특징은 subscriber는 publisher에 대한 정보 없이 Channel에 할당된 작업만 모니터링하다 해당 이벤트에 맞는 메시지를 받으면 작업하게 됩니다. 반대로 publisher또한 subscriber을 모른다는 것입니다.

Pubsub의 장단점

장점

  1. Observer패턴에 비해 Pub-Sub패턴이 더 결합도가 낮습니다.(Loose Coupling)
    Publish-subscribe pattern에서는 출판사와 구독자는 어디에 있어도 상관없습니다. Fragment B가 구독 설정만 하게 되면, 어느 곳에서든 출판되어지는 데이터를 받을 수 있습니다. 사실상 출판사와 구독자 사이를 연결하는, 터널링(Tunneling)을 하는 겁니다. 이렇다 보니, 어떠한 참조 관계도 없이 손 쉽게 다른 객체 간 이벤트를 연결시킬 수 있게 됩니다.

  2. 확장에 용이 합니다.
    Observe pattern의 경우, 하나의 이벤트가 추가 되거나 제거 될 시, 건드려야 할 부분이 많아진다는 단점이 있습니다. 혹여나 같은 Observe 객체를 상속 받거나 구현한 클래스가 있다면, 수정이 그 만큼 커지는 단점이 생기죠. 반면, Publish-scribe pattern은 그럴 걱정이 없습니다. 구독할 대상을 줄이거나, 출판을 하지 않는 것 만으로 내용을 제어할 수 있기 때문이죠.

단점

  1. 일관성이 없습니다.
    가장 큰 단점으로, 일관성이 없다는 점을 들 수 있습니다. 사실 상, 출판과 구독 관계 파악에 어려움이 존재하며, 흐름이 예측이 되지 않을 가능성도 있으며 디버깅에 어려움이 있을 수 있습니다. 즉, 남발하게 된 Publish-subscribe pattern은 Goto 문을 남발한 것과 같은 효과를 가질 수 있다는 단점이 있습니다.

  2. 메시지 관리가 어려울 수 있습니다.
    출판사와 구독자간의 연결이 깨지거나(인스턴스의 소멸), 멀티 쓰레드 등에서 제어 순서 문제 등 관리에 어려움이 있습니다. 간단한 메시지를 주고 받는 용도라면 괜찮지만, 시스템이 메시지 기반으로 돌아가게 된다면 관리 및 제어의 난이도가 높아지게 됩니다.

Observer패턴이란

감시자 패턴이라고도 부르며, 크게 관찰자인 옵저버와 관찰 대상 객체로 구성되어 있습니다.
Observer패턴은 모델-뷰-컨트롤러(Model-View-controller, MVC) 패러다임과 자주 결합합니다.즉 클라이언트 측 자바스크립트 프로그래밍에서 널리 사용되는 패턴입니다.

1. 옵저버(관찰자)

  • 객체의 변화를 감지할 감시자이다.
  • 객체의 상태 변화가 있을 때 동작할 메소드를 가진다. (ex. update())
  • 여러 옵저버가 필요할 시, 옵저버 클래스를 만들고 이 클래스를 상속 받아 옵저버1, 2를 만들 수 있다.

2. 객체(관찰대상)

  • 객체는 해당 객체의 변화를 감시하는 옵저버 리스트를 저장하고 있다.
  • subscribe()를 사용해 옵저버를 추가한다.
  • 객체 상태가 변하면(ex. 상태값 변경, 이벤트 발생) notify()를 사용해 옵저버에게 알려준다.
  • 옵저버는 notify()를 통해 객체 상태 변화를 감지하고, update()를 실행한다.

옵저버 패턴의 작동 방식은 간단합니다. 모듈들에게 옵저버를 등록하여 상태 변화가 있을 때마다 메서드를 통해 옵저버에게 통지하도록 하는 시스템입니다. 모듈들은 상태 변화가 일어났을 대 관찰자(observer)에게 필요한 데이터와 함께 자신의 상태 변화를 통보합니다.

Observer패턴 장단점

장점

  • Subject의 상태 변경을 주기적으로 조회하지 않고 자동으로 감지할 수 있다.
  • 발행자의 코드를 변경하지 않고도 새 구독자 클래스를 도입할 수 있어 개방 폐쇄 원칙(OCP)Visit Website 준수한다.
  • 런타임 시점에서에 발행자와 구독 알림 관계를 맺을 수 있다.
  • 상태를 변경하는 객체(Subject)와 변경을 감지하는 객체(Observer)의 관계를 느슨하게 유지할 수 있다. (느슨한 결합)

*개방 폐쇄의 원칙(OCP)이란 기존의 코드를 변경하지 않으면서, 기능을 추가할 수 있도록 설계가 되어야 한다는 원칙을 말합니다.

단점
- 구독자는 알림 순서를 제어할수 없고, 무작위 순서로 알림을 받음(하드 코딩으로 구현할수는 있겠지만, 복잡성과 결합성만 높아지기 때문에 추천되지는 않는 방법이다.)
- 옵저버 패턴을 자주 구성하면 구조와 동작을 알아보기 힘들어져 코드 복잡도가 증가한다.

  • 다수의 옵저버 객체를 등록 이후 해지하지 않는다면 메모리 누수가 발생할 수도 있다.
    - Pubsub 패턴에 비해서 결합도가 높다.
    Observe pattern의 큰 단점은 결합도가 높아진다는 점에 있습니다. Android를 예로 들자면, 2개의 Fragment A, B가 존재한다고 가정합시다. 이 Fragment는 같은 화면에서 출력되고 있는 같은 레벨의 계층에 속해 있습니다. 이 때, Fragment A의 버튼을 누르면 Fragment A의 내용도, Fragment B의 내용도 함께 변경되어져야 합니다. 그러면 자연스럽게 Fragment A는 Fragment B의 인스턴스를 참조하고 있어야 어떤 상황에서 이벤트를 전달할 수 있습니다. 즉, Fragment A는 Fragment B를 직접 참조하게 되고, 결합도가 높아지게 됩니다. 후에 Fragment A를 대체하고자 한다면, 이 결합도를 해소해야만 대체가 가능해 지게 되겠죠. 만약 Fragment A와 Fragment B가 같이 서로를 참조하고 있다.

Observer 패턴과 Pubsub 패턴의 사용 이유

1. polling을 방지할 수 있다.
polling이란, 상태를 주기적으로 확인하고 만약 조건을 만족할 시 자료처리를 하는 방식이다.
polling의 단점은 짧은 주기로 관찰하면 부하가 발생하며, 긴 주기로 관찰하면 실시간성이 떨어진다는 것이다.

2. 모듈 간의 의존성을 낮출 때 유용하다.

옵저버 패턴이랑 같은건가?

Observer Pattern == PubSub Pattern이 같은 개념이라고 보는 글도 있었고 아니다라는 글이 있었습니다.
위에 특징을 살펴보았을 때 가장 큰 차이점인 중간에 Channel 또는 Topic이 존재하는지 여부에 있어서 엄연히 다른 구조인 거 같다고 생각이 들었습니다.




참고

0개의 댓글