프로그래밍

pub/sub 구조란 무엇인가

2kindsofcs 2020. 2. 12. 19:42

발행-구독 모델, pub/sub system 등 다양한 이름으로 불리고 있지만 이 블로그 글에서는 pub/sub 구조라고 부르려고 한다.

 

우리의 친구 위키피디아를 보면, 정의가 간결하게 잘 적혀있다.

  발행-구독 모델은 비동기 메시징 패러다임이다. 발행-구독 모델에서 발신자의 메시지는 특별한 수신자가 정해져 있지 않다.
  대신 발행된 메시지는 정해진 범주에 따라, 각 범주에 대한 구독을 신청한 수신자에게 전달된다.
  수신자는 발행자에 대한 지식이 없어도 원하는 메시지만을 수신할 수 있다.
  이러한 발행자와 구독자의 디커플링은 더 다이나믹한 네트워크 토폴로지와 높은 확장성을 허용한다.

사실 무슨 말인지 잘 모르겠으니까 보기 힘드니까 포인트별로 짚어보려고 한다. 

 

1) pub/sub 구조에서 수신자는 발행자에 대한 지식 없이 원하는 메세지만을 수신할 수 있다.

 

golang 관련 컨퍼런스가 새로 열릴 때마다 해당 컨퍼런스에 대한 정보를 받고싶어하는 수신자가 있다고 가정하자. 

이 수신자의 관심사는 "새로운 컨퍼런스에 대한 정보"이다. 오로지 그것만 필요한 것이다.

발행자가 누구인지, 어디에 있는지, 뭘 하는 존재인지 같은 건 관심이 없다. 그저 새로운 컨퍼런스가 열린다고 할 때 그에 대한 정보만 받으면 된다. 

 

수신자는 "golang컨퍼런스 알람" 채널을 구독한다. 이 채널에 누가 어떻게 정보를 넣어주는지는 관심사가 아니다. 

 

대략 감이 잡히니까, 이제 정확하게 짚어보면... 

발행자와 수신자 사이에는 브로커 또는 버스라고 불리는 중간 컴포넌트가(앞서 말한 채널에 해당한다) 있다. 발행자는 중간 컴포넌트의 존재를 안다. 수신자도 중간 컴포넌트를 안다. 하지만 발신자와 수신자는 서로를 모른다. 애초에 서로에게 관심도 없다. 중간 컴포넌트만 알면 되기 때문이다.

 

 

2) 발신자의 메세지는 특별한 수신자가 정해져 있지 않다.

 

특별한 수신자가 따로 정해져 있지 않다. 발신자는 메세지를 구독을 신청한 수신자(들)에게 전달할 뿐이다. 

구독을 했으면 메세지를 보내고, 안 했으면 안 보낸다. 

 

 

3) pub/sub 구조는 비동기 메세징 패러다임이다. 

 

Image source:  https://hackernoon.com/observer-vs-pub-sub-pattern-50d3b27f838c

 

즉 비동기 메세징과 관련된 이론적인 틀/방법이라는 것. 동기/비동기 개념을 먼저 짚어보면,

동기는 어떤 일의 수행과 동시에 결과가 나오는 것(정확히는 동시에 나오도록 노력하는 것)이다.
비동기는 어떤 일의 수행 즉시 결과가 나온다는 보장이 애초에 없는 것이다. Node.js의 콜백이 전형적인 비동기의 예시다. 

 

발행자는 이벤트가 발생했을 때마다 중간 컴포넌트(브로커 또는 버스)에게 알려준다. 그러면 중간 컴포넌트는 각 이벤트들을 잘 필터링해서 받아야 할 수신자들에게 고루 보내준다. 즉 이벤트가 발생했다고 해서 곧바로 수신자가 그 정보를 얻을 수 있는 것은 아니다.

이벤트가 발생했다고 해서 발행자가 곧바로 수신자에게 정보를 넘겨주는 것이 아니기 때문이다. (observer 패턴에 대해서도 정리를 한번 하면 좋겠다.) 

 

여기서 "곧바로" 라는 단어에 주의할 필요가 있다고 생각한다. 예를 들어 A라는 이벤트가 발생해서 발행자가 해당 이벤트에 대한 정보를 중간 컴포넌트에게 넘겨줬다고 하자. 중간 컴포넌트는 A 이벤트에 대한 정보를 구독한 수신자에게 정보를 보내주었다. A 이벤트가 발생한 시점부터 수신자가 정보를 받는 시점까지 0.00000000000000001초가 걸렸다고 가정하자. 이벤트가 발생하자마자 수신자가 정보를 얻은 것이나 다름 없지 않나? 비동기가 아니라 동기 아닌가? 

 

발행자가 이벤트를 중간 컴포넌트에게 알려주고 나면, 발행자는 더 이상 그 이벤트에 신경쓰지 않는다. 중간 컴포넌트에게 이벤트를 알려주는 행위를 하고 난 다음, 그 행위의 결과를 기다리지 않고 바로 다른 자기 할일을 한다. 중간 컴포넌트가 A 이벤트를 구독하는 수신인을 추려서 정보를 보내주는 과정에서 시간이 얼마나 걸릴지, A 이벤트에 대한 정보가 수신인에게 잘 전달되었는지 등을 발행자는 전혀 신경쓰지 않는다. 따라서 A 이벤트가 발생하고 나서 수신인이 해당 이벤트에 대한 정보를 얻기까지 0.00000000000000001초가 걸리든, 10초가 걸리든 비동기 동작이다. 

 

동기/비동기 개념을 짚어봤으니까, 이제 "왜" 비동기 메세징을 하는지를 생각해보면,  

"아~ 심심한데 비동기 메세징 패러다임이나 만들어볼까?"하고 나온 게 당연히 아닐 것이다. 

여느 라이브러리, 프로토콜 등이 그렇듯이 어떤 문제가 있는데, 그 문제를 해결하고 싶어서 나온 게 pub-sub 구조라고 생각한다. 

 

1. 브로드캐스팅의 관점: 내가 관찰하고 있는 어떤 대상에게 특정 이벤트가 일어나면, 그것을 관련된 다른 대상들에게 효율적으로 알려주고 싶다.

2. 디커플링의 관점: 그런데 이벤트를 통지받아야 하는 대상들을 내가 일일이 관리하지 않고, 종속 관계를 느슨하게 하고 싶다. 

 

1과 2의 관점을 만족시키는 구조가 필요했고, 이에 대한 직관적인 해답으로서 pub-sub 구조가 나온 것이라고 생각한다. 

 


pub-sub구조는 특성상 일방향으로 수신자가 이벤트에 대한 정보를 얻기만 하면 되는 경우처럼 Active-Passive한 구조로 전달만 하면 되는 경우에 유용하다. Redis에서도 pub-sub 모델을 지원하는데, 한번 보면 좋을 것 같다. 

 


참고 페이지)

https://hackernoon.com/observer-vs-pub-sub-pattern-50d3b27f838c

 

반응형