Design Pattern: Publish-Subject Pros and Cons

WindSekirun (wind.seo)·2022년 4월 26일
0

이 글은 기존 운영했던 WordPress 블로그인 PyxisPub: Development Life (pyxispub.uzuki.live) 에서 가져온 글 입니다. 모든 글을 가져오지는 않으며, 작성 시점과 현재 시점에는 차이가 많이 존재합니다.

작성 시점: 2017-10-17

소개

Publish-Subject 패턴 (발행-구독) 패턴은 Event-Driven Programming 에서 쓰이는 방법으로 발행자와 구독자로 역할을 나누어 발행자에서 구독자로 특정한 이벤트를 발송하는 것이다.


이미지 출처: http://reactivex.io/documentation/operators/images/S.PublishSubject.png

마블 다이어그램으로 설명하면 위와 비슷한데, 하나씩 사례를 들어가면서 설명하면...

맨 위가 발행자, 밑이 구독자 로 첫번째 구독자(A1) 는 처음부터 발행자를 구독하고 두번째 구독자(B1) 는 중간에 발행자를 구독한다.

여기서 구독한다는 말은 발행자의 행동을 전부 받는다는 뜻이다.

흔히 '구독' 개념이 쓰이는 유투브의 사례가 이 패턴을 자세히 설명한다.

시청자가 채널을 '구독' 하고, 채널이 새로운 영상을 올리면 시청자에게 알림으로 영상을 올렸다는 알림이나 리스트가 뜨게 된다.

발행자가 $a, $b, $c 라는 이벤트를 시간 차를 두고 보낸다고 하면

구독자 A1는 $a, $b, $c 라는 이벤트를 받을 수 있고, 구독자 B1는 $b가 발행자로부터 발송된 이후 구독하였으므로 $c만 받을 수 있다.

보통 프로그래밍에서 A와 B라는 클래스를 서로 연결하기 위해서는 상속 또는 Listener 등의 패턴으로 단단한 커플링을 결합하나 이 Publish-Subject는 매우 느슨한 커플링을 결합할 수 있게 해주어 A와 B가 구조로부터 분리되어 각자에 영향을 덜 미치게 만들 수 있다.

안드로이드 에서는..?

Otto, EventBus 등으로 쉽게 구현할 수 있고, 언어 자체가 Observable 하게 구성된 RxJava를 이용할 수 있다.

장점

느슨한 커플링 결합

위에서도 언급했었다 싶이, A와 B라는 클래스를 서로 연결하기 위해서는 상속(Inherit) 나 Listener 등의 패턴으로 구성하게 된다.

상속이나 Listener 패턴의 문제점은 A와 B라는 클래스를 서로 강력하게 결합한다는 것에 있다. 그 말인 즉슨, A와 B 한쪽이 변하면 다른 한쪽도 변한다는 의미이다.

그에 비해 Publish-Subject 패턴을 사용하게 되면 A와 B는 느슨한 커플링으로 결합되며 이는 독립적인 프로세스를 유지할 수 있게 해준다.

한 쪽을 많이 변경한다고 해도 그에 생길 수 있는 B에 대한 사이드 이펙트, 상태(State) 고려를 하지 않아도 된다.

또한 결합할 때에 있어 다른 클래스 간의 코드 디자인을 고려하지 않아도 된다.

확장성

한 발행자에는 여러 구독자가 붙을 수 있어 같은 행동을 받아야 한다면 여러 곳에서 쉽게 받을 수 있는 등 그 자체의 유연성이 있다.

하지만 과하면 부하가 걸리기도 한다.

단점

기존 패턴에 비해 강력한 장점을 제공하는 만큼, 그 만큼의 단점이 생긴다.

구독자, 발행자의 상태를 알기 어려움

장점에서 말했듯이 구독자와 발행자는 서로 느슨하게 연결된다.

그렇기에 메세지가 성공적으로 발송되었는지 실패하였는지 알기 어렵다.

또한 상태 고려를 하지 않기에 구독자는 발행자의 상태를 알 수 없고, 마찬가지로 발행자는 구독자의 상태를 알 수 없다.

느슨한 커플링이기 때문에 발행자가 아무리 행동을 보내도 구독자가 못 받을 수 있다.

구독자와 발행자가 늘어나면서 부하가 생김

구독자와 발행자 간의 주고 받는 메세지 수가 늘어나면서 자연스럽게 부하가 생긴다.

한꺼번에 많은 양을 전송하거나, 짧은 주기로 전송하게 되면 메세지가 정상적으로 발송되지 않던 문제가 있다.

만약 UI 갱신을 Publish-Subject 패턴이 담당하게 된다면 어느 한 순간부터 UI 갱신이 멈추는 일도 허다하다.

악성 발행자가 침입할 수 있음

구독자와 발행자 간의 주고 받는 것은 메세지 이다. 서로의 상태를 알 수 없기에 발행자가 누구인지 구독자는 모르게 된다. 그렇기에 악성적인 발행자가 침입하여 구독자가 악성 발행자가 발행한 이벤트를 받게 되면 전체적인 구조가 파괴될 수 있다.

코드 복잡성 증가

구독자와 발행자 간의 주고 받는 메세지의 규약, 구독자의 규칙 등으로 코드에 추가적인 작업이 필요하다.

결론

분명히 Publish-Subject 는 기존 구조가 제공하던 강력한 결합에서 느슨한 결합을 제공해서 독립적인 프로세스를 유지하면서도 서로간의 클래스를 연결시킬 수도 있다.

하지만 그에 해당하는 단점은 분명히 있어 쓰더라도 조금 생각해서 쓸 필요는 있다.

잡담

최근 EventBus 계열로 서비스 <-> 액티비티 <-> 다이얼로그 간 통신을 구현했었는데 결국 부하가 걸려서 작동을 멈추는 사건이 있었다.

그 이슈 이후로 EventBus 계열이 그 프로젝트에서는 전부 빠지게 되고 상속이나 바인드 서비스 등으로 처리했고 최소한의 느슨한 통신이 필요한 경우에는 Broadcast로 대체했다는 이야기는 접어두자...

profile
Android Developer @kakaobank

0개의 댓글