Spring Boot와 RabbitMQ를 활용한 메세징 서비스 구성하기

조경민·2024년 3월 19일
0
post-thumbnail

메세지 브로커

본격적으로 시스템을 구성하기에 앞서 간단한 퀴즈를 내어보겠습니다. 홈 IoT, 스마트팜, 주식/선물 거래, SNS 등의 공통점이 무엇인지 혹시 눈치채셨나요? 바로 짧은 시간 간격으로 생성된 데이터를 수집하고 이를 다른 어플리케이션에 송신하여 다양한 목적에 알맞게 활용한다는 점입니다. 만약 데이터가 처리되는 과정에서 유실되거나 엉뚱한 곳에 전달되면 서비스 운영에 적지 않은 해를 끼치게 되겠죠. 이 때 해결사 역할을 하는 것이 바로 메세지 브로커인 RabbitMQ 입니다.

메세지 브로커라는 표현이 다소 생소할 수 있는데요, 다음 그림을 통해 쉽게 알아봅시다.

어떤 물건 혹은 문서를 다른 곳에 보내기 위해서 우리는 우체국에 갑니다. 그리고 목적이나 성격에 맞춰 우편물을 접수한 후 배송되기를 기다리죠. 배송이 완료되면 문자 혹은 스마트폰의 어플리케이션으로 알람을 받게되고 우편물 수신자는 보내고자 했던 물건이 안전하게 잘 배송되었는지 확인합니다.

RabbitMQ

RabbitMQ는 위와 같이 서비스 혹은 어플리케이션에서 발생하는 다양한 메세지를 받아서 목적지에 알맞게 보내주는 중개 역할을 하며, 공식 홈페이지에는 다음과 같이 서비스를 소개하고 있습니다.

RabbitMQ is a reliable and mature messaging and streaming broker.
RabbitMQ는 안정적이고 성숙한 메시징 및 스트리밍 브로커입니다.

RabbitMQ는 Advanced Message Queuing Protocol(이하 AMQP)라는 개방형 메세징 프로토콜을 기반으로 동작합니다. 이기종 간의 메세징을 효율적으로 처리할 수 있으며, 목적지에 따라 안전하게 메세지를 전달할 수 있는 것이 바로 이 AMQP 프로토콜 덕분입니다. 본격적으로 Spring Boot와 RabbitMQ를 연동하기 전에 각 구성요소 및 동작하는 방식을 살펴보겠습니다.

  • Publisher(발행자): 메세지를 발행하는 주체
  • Consumer(소비자): 메세지를 사용(소비)하는 주체
  • Exchange: 발행된 메세지가 처음 도착하는 곳이며, 타입 및 Binding에 따라 메세지를 각 queue에 분배
  • Queue: 메세지가 소비되기를 대기하는 대기열이자 목적지이며, 소비자는 queue를 구독하여 필요한 메세지를 소비
  • Route: Exchange가 queue에 분배되는 과정

처음에는 막연히 복잡하다고 느껴졌던 RabbitMQ는 기본적으로 위와 같은 형태로 동작합니다. 여기서 중요한 점은 소비자가 정상적으로 메세지를 수신했다고 RabbitMQ에 알려주어야 비로소 queue에서 해당 메세지를 삭제한다는 것입니다. 만약 정상적으로 메세지를 수신하지 못했다면 메세지는 소비될 때까지 queue에 대기하게 되죠. 이것이 바로 AMQP의 메세지 승인 개념입니다. 네트워크가 불안정하거나 서비스가 오류로 다운되었을 때에도 메세지를 안전하게 관리할 수 있기 때문에 다양한 방면에 활용됩니다.

Exchange는 어떤 queue로 메세지를 보낼 지를 결정합니다. 이 때 목적지를 정하는 요소는 Exchange 타입과 Binding 입니다.
먼저 Exchange 타입은 아래와 같이 네 가지가 있습니다.

  • Direct: 선언한 이름이 없으며, 라우팅 키를 통해 직접 라우팅 가능
  • Fanout: Exchange에 바인드 된 모든 queue에 메세지 전송
  • Topic: 라우팅 키와 지정한 패턴에 의해 메세지 전송
  • Headers: 라우팅 키 대신 헤더 정보를 통해 메세지 전송

이번 포스트에서는 여러 유형 중, Direct 방식으로 메세징 서비스를 구성해보도록 하겠습니다.

실습

버전 정보

  • JDK 17
  • Spring Boot 3.2.3
  • RabbitMQ 3.12.12

준비 사항

GitHub 저장소

실습은 아래의 두 Spring Boot 어플리케이션을 통해 진행됩니다. 저장소를 clone 하거나 fork 해주세요.

따라하기

RabbitMQ 배포

  1. 클라우드타입에 로그인 후 우측 네비바의 ➕ 버튼을 눌러 새 프로젝트 창을 띄우고 프로젝트 이름과 표시 이름을 입력한 뒤 생성하기 버튼을 누릅니다.

  2. 가운데 ➕ 버튼을 누르고 RabbitMQ 템플릿을 선택합니다. 이어서 버전은 3.12로 선택하고 설정하고자 하는 Username과 Password를 입력한 뒤 배포하기 버튼을 누릅니다. 이 때, 서비스 이름은 프로젝트 내부에서 호스트명으로 참조되므로 rabbitmq에서 수정하지 않고 진행하도록 합니다.

  3. 연결 탭에 두 개의 주소가 생성되었는지 확인합니다. 하늘색으로 표시된 주소는 프로젝트 내부에서 참조할 수 있는 URL입니다.

Spring Boot Producer 배포

  1. 미리 구성된 Producer 어플리케이션을 띄우기 전 application.properties 의 설정 정보를 확인합니다.

    
    spring.application.name=spring-rabbit-producer
    
    rabbitmq.queue=chat_notification
    rabbitmq.exchange=chat_exchange
    rabbitmq.routingkey=chat_routingkey
    
    spring.rabbitmq.host=${RABBITMQ_HOST}
    spring.rabbitmq.port=${RABBITMQ_PORT}
    spring.rabbitmq.username=${RABBITMQ_USERNAME}
    spring.rabbitmq.password=${RABBITMQ_PASSWORD}
    
  2. 클라우드타입의 프로젝트 페이지에서 ➕ 버튼을 누르고 Spring Boot를 선택한 후, 미리 fork 해놓은 spring-rabbit-producer 를 선택합니다. 기타 설정은 아래를 참고하여 입력한 후 배포하기 버튼을 클릭합니다.

    • 버전: v17
    • 환경변수(Environment Variables)
      • RABBITMQ_HOST: rabbitmq
      • RABBITMQ_PORT: 5672
      • RABBITMQ_USERNAME: 설정했던 Username
      • RABBITMQ_PASSWORD: 설정했던 Password
      • TZ: Asia/Seoul
  3. 배포가 완료되면 Spring Boot Producer 어플리케이션 페이지의 연결 탭에서 https:// 로 시작되는 URL을 확인합니다. 추후 API를 호출하는 주소로 사용됩니다.

Spring Boot Producer 테스트

  1. 메세지를 Producer에서 생성한 후 RabbitMQ로 보내기 위한 API를 호출해 보겠습니다. 먼저 크롬 브라우저에서 Talend API Tester를 켭니다.

  2. API를 호출하기 위한 설정 및 정보를 입력합니다.

    • METHOD: POST
    • 주소: <배포한 Spring Boot Producer의 URL>/publish
    • BODY
      {
        "sender":"john",
        "receiver":"mary",
        "message":"Hello!"
      }
  3. Send 버튼을 누르고 다음과 같이 정상 응답 코드 및 메세지가 표시되는지 확인합니다.

  4. 클라우드타입에 배포된 RabbitMQ 페이지의 연결 탭에서 https://로 시작되는 URL을 브라우저 주소창에 입력하여 대시보드를 켜고 Queues and Streams 탭으로 이동합니다. 이어서 생성되어 있는 queue의 이름를 클릭합니다.

  5. 여러 항목 중, Get messages를 클릭하고 Get message(s) 버튼을 누릅니다. 아직 consumer에 의해 소비되지 않았기 때문에 메세지가 queue에 대기 중인 것을 알 수 있습니다.

Spring Boot Consumer 배포 및 테스트

  1. 미리 구성된 Consumer 어플리케이션을 띄우기 전 application.properties 의 설정 정보를 확인합니다.

    
    spring.rabbitmq.host=${RABBITMQ_HOST}
    spring.rabbitmq.port=${RABBITMQ_PORT}
    spring.rabbitmq.username=${RABBITMQ_USERNAME}
    spring.rabbitmq.password=${RABBITMQ_PASSWORD}
    
  2. 클라우드타입의 프로젝트 페이지에서 ➕ 버튼을 누르고 Spring Boot를 선택한 후, 미리 fork 해놓은 spring-rabbit-consumer 를 선택합니다. 기타 설정은 아래를 참고하여 입력한 후 배포하기 버튼을 클릭합니다.

    • 버전: v17
    • 환경변수(Environment Variables)
      • RABBITMQ_HOST: rabbitmq
      • RABBITMQ_PORT: 5672
      • RABBITMQ_USERNAME: 설정했던 Username
      • RABBITMQ_PASSWORD: 설정했던 Password
      • TZ: Asia/Seoul
  3. 배포가 완료되면 터미널 아이콘을 눌러 실행 로그 창을 켭니다. Producer API를 호출하여 생성된 메세지가 정상적으로 로그에 표시되면 정상적으로 Consumer가 작동한 것입니다.

  4. RabbitMQ 대시보드에서 이전과 같이 Get Message(s) 버튼을 눌러 queue에 대기 중인 메세지를 조회해보면 빈(empty) 상태라는 메세지가 뜹니다. 이는 구동된 Consumer 어플리케이션이 해당 메세지를 사용했기 때문에 RabbitMQ가 이를 삭제한 것입니다.

Reference

profile
Live And Let Live!

0개의 댓글