ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [WebFlux] publisher(발행) - subscriber(구독) 패턴에 대해서
    웹 개발/WebFlux 2020. 1. 24. 16:00

    publisher(발행) - subscriber(구독)패턴에 대해서

    처음 WebFlux를 썼을 때, publisher와 subscriber 모델의 개념을 이해하지 못해서 삽질을 많이했다.

     

    spring mvc로 동기식 개발을 할 때는 메서드 호출만 하면 결과값이 return 됐었다.

    그러나, reactive하게 동작하는 WebFlux에서는 메서드만 호출해서는 아무 일이 일어나지 않는다. (reactive 선언문)


    개념

    publihser - subscriber패턴observer 디자인 패턴과 유사한 부분이 많다.

     

    옵저버 패턴

    위키피디아의 옵저버 패턴 설명을 보자.

    옵서버 패턴(observer pattern)은 객체(subject)의 상태 변화를 관찰하는 관찰자들, 즉 옵저버들(observers)의 목록을 객체에 등록하여 상태 변화가 있을 때마다 메서드 등을 통해 객체가 직접 목록의 각 옵저버에게 통지하도록 하는 디자인 패턴이다. 주로 분산 이벤트 핸들링 시스템을 구현하는 데 사용된다. 발행/구독 모델로 알려져 있기도 하다.

     

    객체가 변할 때마다 옵저버에게 객체의 정보를 알려주는 디자인 패턴이다.

     

    발행 - 구독 패턴

    아래는 발행-구독 패턴의 설명이다.

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

    발행-구독은 메시지 큐 패러다임과 형제같은 관계로, 일반적으로 대형 메시지 지향 미들웨어 솔루션의 일부이다. 대부분의 메시징 시스템의 API(예: JMS)들은 발행-구독과 메시지 큐 모델을 모두 지원한다.

     

    어떤 차이점이 있는걸까?

    'difference between observer and publisher subscriber' 라는 검색어로 구글링을 했을 때 탑랭크로 올라와있는 포스팅을 참고 삼았다.
    옵저버 패턴에서 객체(subject)가 옵저버(observer)에게 객체의 상태를 알려준다는 부분이 publisher-subscriber 패턴과 유사하다. (subject = publisher, observer = subscriber)


    publisher-subscriber 패턴에서 메시지 송신자(publisher)는 정해진 수신자(specific receivers called subscriber)와 직접적 메시지를 통신하지 않는다. 그 둘 사이에 브로커 또는 메시지 브로커 또는 이벤트 버스(broker or message broker or event bus)라고 불리는 제 3의 구성요소가 있다.

    Event bus
    모든 들어오는 메시지를 필터링하고 다시 메시지들을 배포한다.


    다시 말해, 발행-구독 패턴은 다른 시스템 컴포넌트 간에 서로 알지 못하더라도 소통할 수 있도록 해주는 패턴이다.

     

    브로커가 이 모든 메시지들을 어떻게 처리할까? 실제로, 메시지 필터링을 위한 몇 개의 프로세스들이 있다. 대부분 사용하는 방식은 크게 두가지가 있는데, topic-based systemcontent-based system이다. 자세한건 여기로. (메시지 필터링 부문을 참고하면 된다)

     

    요약하자면

    구성 옵저버 패턴 구독-발행 패턴
    의존성 옵저버 패턴은 옵저버들이 객체들을 알고 있고, 객체들은 옵저버들의 기록을 가지고 있다. publisher와 subscriber는 서로 몰라도 되고, 메시지 큐들이나 브로커를 통해서 소통한다.
    비교했을 때 결합성 높음 낮음
    구현방식 대부분 동기 방식(이벤트 발생 시, 객체가 모든 옵저버의 적절한 메서드들을 호출) 비동기 방식(메시지 큐 사용)
    확장성 하나의 애플리케이션에서 구현 크로스 애플리케이션 구현

     

    이렇게 차이가 있다하지만, 구독-발행 패턴은 옵저버 패턴의 변화된 형태라 보면 좋겠다. 개념적으로 상당히 유사하기 때문이다. 그래서 꼭 딱딱 정확하게 둘의 차이점을 나눌 필요는 없다.

     

    WebFlux는 중간의 broker가 존재하지 않기 때문에 WebFlux에서는 옵저버패턴과 구독-발행 패턴을 유사하게 생각한 방식으로 생각하면 될 것 같다.

    WebFlux에서 유의사항

    subscribe하지 않으면 결국 아무 일도 일어나지 않는다는 의미이다.

     

    subscribe함으로써 publisher와 subscriber는 연결되고, subscriber로부터 publisher로 upstream으로 요청하여 publisher가 동작하도록 만드는 것이다.

    이를 subscriber가 publisher를 pulling(당기다)한다고 표현한다. 또는 publisher가 subscriber로 push 한다고도 말한다.

     

    마치 신문을 구독하는 사람이 없으면 신문을 발행하지 않는다라고 할까? 수요가 없어서 공급이 없는 느낌이다. 비유하자면 수요자가 있어야 공급자가 생긴다 정도.

     

    그렇다고 메서드를 subscribe해서 결과값을 return 해줄 필요없다. 스프링 내부적으로 controller에서 return된 publisher를 subscribe 해주므로 아래 예시처럼 publisher를 return 해주면 된다. (Netty로 사용중일 경우, HttpServerHandle 클래스의 onStateChange 메서드에서 subscribe한다. Servlet의 경우, ServletHttpHandlerAdapter 클래스의 service 메서드에서 subscribe한다.)

        @GetMapping("/")
        public Mono<String> hello() {
            return Mono.just("hello"); // 또는 publisher를 반환하는 메서드 : helloService.findOneWord();
        }

     

    출처

Designed by Tistory.