인프런 영문 브랜드 로고
인프런 영문 브랜드 로고

인프런 커뮤니티 질문&답변

hoonseung님의 프로필 이미지

작성한 질문수

RabbitMQ를 이용한 비동기 아키텍처 한방에 해결하기

12.Pub-Sub모델을 이용한 실시간 알림 (WebSocket, STOMP 이용) part 3

tutorial-step4 질문

해결된 질문

작성

·

82

0

안녕하세요 해당 챕터에서 듣던 중 궁금한 점이 있습니다.

FanoutExchange, java, spring, vue queue 이렇게 세가지를 바인딩 설정을 하였는데 FanoutExchange는 메세지를 발행하면 바인딩 설정된 모든 큐에 메세지를 전달하는것으로 이해했습니다.

그리고 rabbitTemplate.convertAndSend(fanoutExchange, news(라우팅키) , message) 이렇게 pub에서 발행,

sub 에서는 3개의 rabbitListner 들이 있던데 이렇게 되면

3개의 sub 메세지를 다 받아야 되는게 아닌가 싶어서요.

강의를 보면은 java로 보내면 java큐에만 메세지가 들어가서 sub이 받는거 같더라구요 이 부분이 이해가 안갑니다..

 

답변 2

1

코드빌런님의 프로필 이미지
코드빌런
지식공유자

안녕하세요. 수강자님

FanoutExchange는 라우팅 키를 무시하고 전체 브로드캐스트 되므로 질문하신 내용이 맞습니다. (아마 강의중간에 Fanout에서는 라우팅 키를 무시한다고 설명한 부분이 있을겁니다)

다만, 클라이언트의 설정(WebSocket)에 의해 특정 토픽만 구독하기 때문에 원하는 뉴스만 받게 됩니다.

RabbitMQ에서 Consumer로 갈때는 fanout이기 때문에 모든 큐에 뉴스가 전달이 되고 Consumer에서 WebSocket에 전달되는 구조에서는 config.enableSimpleBroker("/topic"); 와 WebSocket의 SimpMessagingTemplate을 사용한 설정으로 인해 클라이언트가 해당하는 토픽(/topic/java)만 구독을 하게 됩니다. WebSocket은 모든 클라이언트에게 메시지를 보낼수도 있고, 특정 토픽만 선택적으로 필터링 해서 전달할수도 있습니다.

 

만약 웹소켓을 쓰지 않고 특정 토픽에 전달해서 해당 뉴스만 구독해야 한다면 Direct나 Topic 익스체인지를 써야 동일하게 동작하게 됩니다. 다만 이 경우 모든 클라이언트가 메시지를 받아야 하는 경우는 부적합 합니다.

정리하면 Fanout은 모든 큐에 메시지를 브로드캐스트하지만 WebSocket을 이용해 특정 뉴스 타입만 선택적으로 구독할 수 있습니다. (서로 독립적으로 동작합니다)

따라서 Pub/Sub의 성격을 이용해서 브로드 캐스트를 하는 것은 Direct나 Topic 보다 Fanout이 적합하고, 전체 브로드캐스트가 필요하지 않은 Pub/Sub의 일부 제한이 필요한 경우는 WebSocket과 STOMP를 통헤서 필터링 할 수 있다고 이해하시면 될거 같습니다.

 

감사합니다.

 

hoonseung님의 프로필 이미지
hoonseung
질문자

넵 websocket은 특정 topic을 구독한 사람에게만 전달되는 것으로 이해했습니다. 감사합니다.

그리고.. restApi 호출 부분에서요

@PostMapping("/publish")
public ResponseEntity<String> publishNews(@RequestParam String newsType) {
    String result = newsPublisher.publishAPI(newsType);
    return ResponseEntity.ok("# Message published to RabbitMQ: " + result);
}
private String publishMessage(String news, String messageSuffix) {
    String message = news + messageSuffix;
    rabbitTemplate.convertAndSend(RabbitMQConfig.FANOUT_EXCHANGE_FOR_NEWS, news, message);
    System.out.println("News Published: " + message);
    return message;
}

public String publish(String news) {
    return publishMessage(news, " 관련 새 소식이 있어요!");
}

public String publishAPI(String news) {
    return publishMessage(news, " - 관련 새 소식이 나왔습니다. (API)");
}

RabbitMQ에서 Consumer로 갈때는 fanout이기 때문에 모든 큐에 뉴스가 전달이 되고 <- 이 말씀이

여기 convertAndSend 에 news라는 라우팅 키에

java, spring 이던 어떤 라우팅 키를 주어도 모든 큐에 들어가던데 이 부분인거죠?

코드빌런님의 프로필 이미지
코드빌런
지식공유자

네 맞습니다.

 

해당 예제를 다이렉트로 변경해서 프론트에 뿌리면 해당 라우팅 키만 화면에 보이실거에요.

0

인프런 AI 인턴님의 프로필 이미지

안녕하세요, 인프런 AI 인턴입니다. hoonseung님.

Fanout Exchange의 동작 방식과 관련해 궁금하신 점에 대해 설명하겠습니다.

  1. Fanout Exchange: Fanout Exchange는 메시지를 발행하면 바인딩된 모든 큐로 메시지를 전달하는 방식입니다. 라우팅 키는 이 상황에서는 무시됩니다. 그렇기 때문에, Fanout Exchange에 메시지를 발행하면, 해당 Exchange와 바인딩된 모든 큐로 메시지가 전송됩니다.

  2. rabbitTemplate.convertAndSend 사용 시의 혼동: 말씀하신 rabbitTemplate.convertAndSend(fanoutExchange, news, message) 라인에서 news를 라우팅 키로 사용하셨다고 이해하셨을 겁니다. 그러나 Fanout Exchange에서는 라우팅 키가 무시됩니다. 따라서, 발행된 메시지는 Fanout Exchange에 바인딩된 모든 큐에 전송되어야 합니다.

  3. 실제 동작 간의 차이점: 강의를 들으신 후 java, spring, vue 큐 중 특정 큐에만 메시지가 들어가는 것처럼 보인다면, 이는 RabbitMQ의 설정을 확인해야 할 부분입니다. Fanout Exchange라면 모든 바인딩된 큐에 메시지가 들어가야 정상입니다.

혹시 큐가 특정 조건에 의해 다른 곳으로 바인딩되거나, 직접 교환기에 바인딩되지 않는다면 그럴 수 있습니다. 또한, 메시지 수신과 관련된 Listener들(브로커의 컨슈머 역할)에 대한 확인도 필요합니다. 바인딩 설정에 특별한 설정이 되어 있거나, 일종의 조건 기반 필터링이 작동하고 있을 가능성이 있습니다.

이해가 안 가시는 부분을 더 잘 해결하기 위해서는 강의의 설정 부분을 다시 확인하시는 것이 좋겠습니다. 이와 관련된 추가 정보나 실습을 다룬 강의 내용을 다시 보시는 것을 추천드립니다.

이와 유사한 주제로 기존에 있었던 질문들에 대해 도움이 될 만한 링크를 추천드립니다:

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.