RabbitMQ를 이용해 초간단 메시지 전송예제를 따라해봤습니다.

 

순서

1. rabbitmq 서버 실행

2. 유저 및 VirtualHost 추가

3. 프로젝트생성

4. application.yml 작성

5. RabbitMQConfig.java 작성

6. Message Sender 구현

7. Message Receiver 구현

8. 메시지 전송 테스트

 


 

 

 

환경

OS : Window

IDE : Intellij Community

JDK : 17

 

1. 서버 실행

 

윈도우에서 RabbitMQ를 설치하고 환경변수까지 설정하면 RabbitMQ가 백그라운드에서 실행되고 있을거에요.

윈도우키 눌러서 rabbitmq 검색해서 나오는 저 앱들을 통해 백그라운드 실행을 관리할 수 있습니다.

저는 일단 stop으로 백그라운드에서 실행되는걸 멈췄고,

 

cmd에서 rabbitmq-server를 입력해주면

 

#으로 나름 토끼모양...을 그리면서 실행됩니다.

 

http://localhost:15672/

 

실행하고 난 뒤에 위 주소로 들어가진다면 성공.

 

2. 유저 및 VHost 추가

저는 기본계정을 삭제하고 admin이라는 새로운 계정을 만들었는데,

 

Add a user를 통해 테스트용 계정을 하나 더 생성했습니다.

그리고 처음 생성하면 Can access virtual hosts에 아래처럼 나올텐데

Name에서 직접 계정누르고 들어가서

 

Set permissions 버튼 누르면

이제 virtual host에 접근할 수 있습니다.

 

3. 프로젝트 생성

 

이제 https://start.spring.io/ 에 들어가서

 

Dependency 를 web, devtool, RabbitMQ 세 가지만 추가하고 프로젝트를 생성해줍니다.

적당히 서버 실행 잘 되는지 확인하고

 

4. application.yml 작성

 

application.yml을 아래와 같이 작성해줍니다.

spring:
  rabbitmq:
    host: localhost
    port: 5672
    username: guestuser
    password: guestuser
  application:
    name: HelloMessageQueue
server:
  port: 8080

 

application name이랑 server port는 명시적으로 해줍니다

 

이제 기본 환경 세팅 끝!

 

5. RabbitMQConfig.java 작성

 

이제 RabbitMQConfig 파일을 작성해줄겁니다.

RabbitMQConfig  에서Bean을 4개 만들어줄건데,


- Queue queue() : Queue 인스턴스를 생성하고, Application이 사용할 큐를 정의하고 메시지를 전달하고 처리하는 기본 큐 세팅입니다. 

 

- RabbitTemplate rabbitTemplate(ConnectionFactory ConnectionFactory) : RabbitMQ와 통신하기 위한 템플릿 인스턴스를 생성하는 역할입니다. 메시지 송수신용

 

- SimpleMessageListenerContainer container(ConnectionFactory connectionFactory, MessageListenerAdapter listenerAdapter)

 

- MessageListenerAdapter listenerAdapter(Receiver receiver) : 수신한 메시지를 특정 클래스의 특정 메서드로 전달하는 어댑터, 인자로 전달된 메서드를 자동으로 호출합니다

 

위 의 Bean을 모두 구현한 코드는 아래와 같습니다.

package com.example.HelloMessageQueue.step1;

import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class RabbitMQConfig {
    
    public static final String QUEUE_NAME = "helloqueue";

    @Bean
    public Queue queue(){
        /**
         * Queue 생성자로 name과 durable(Boolean) 받음
         * durable : 휘발성이냐 아니냐 (volatile, persistent)
         * false로 주면 휘발성 - volatile -> 서버가 종료되거나 시작될 때 큐의 메시지가 사라짐
         * true로 주면 영속성 - persistent
         */
        return new Queue(QUEUE_NAME, false);
    }

    @Bean
    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory){
        return new RabbitTemplate(connectionFactory);
    }

    @Bean
    public SimpleMessageListenerContainer container(ConnectionFactory connectionFactory,
                                                    MessageListenerAdapter listenerAdapter){
        SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
        container.setConnectionFactory(connectionFactory);
        container.setQueueNames(QUEUE_NAME);
        container.setMessageListener(listenerAdapter);
        return container;
    }

    @Bean
    public MessageListenerAdapter listenerAdapter(Receiver receiver){
        return new MessageListenerAdapter(receiver, "receiveMessage");
    }
}

 

이제 각 Bean을 하나씩 살펴보면

 

 

@Bean
public Queue queue(){
    /**
     * Queue 생성자로 name과 durable(Boolean) 받음
     * durable : 휘발성이냐 아니냐 (volatile, persistent)
     * false로 주면 휘발성 - volatile -> 서버가 종료되거나 시작될 때 큐의 메시지가 사라짐
     * true로 주면 영속성 - persistent
     */
    return new Queue(QUEUE_NAME, false);
}

 

생성자의 인자로 두 가지를 받는데 첫 번째는 QUEUE_NAME, 다음은 boolean타입의 duration 입니다.큐네임은 말그대로 메시지가 쌓이고 처리될 큐의 이름을 지정하는 것이고duration은 큐가 휘발성인지, 영속성인지 여부를 정하는 옵션입니다.false로 설정하면 서버가 종료되거나 재시작 할 때 큐의 메시지가 사라집니다.

 

 

@Bean
public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory){
    return new RabbitTemplate(connectionFactory);
}

 

JDBCTemplate과 비슷하게 RabbitMQ와 상호작용하기 위한 간단한 API를 제공합니다.
주로 메시지 전송을 담당합니다.
ConnectionFactory는 RabbitMQ와의 연결을 관리하는 객체로 rabbitTemplate에 주입하여 메시지를 전송할 때 사용할 Connection을 제공합니다.
메시지를 전송하는 Sender가 rabbitTemplate.convertAndSend() 메서드를 사용해 큐에 메시지를 넣는데 사용합니다

 

@Bean
public SimpleMessageListenerContainer container(ConnectionFactory connectionFactory,
                                                MessageListenerAdapter listenerAdapter){
    SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
    container.setConnectionFactory(connectionFactory);
    container.setQueueNames(QUEUE_NAME);
    container.setMessageListener(listenerAdapter);
    return container;
}

 

RabbitMQ 메시지를 비동기적으로 수신하기 위해 SimpleMessageListenerContainer 를 생성, 이 컨테이너가 특정 큐를 지속적으로 모니터링하고 메시지를 수신하면 지정된 리스너(MessageListenerAdapter)를 통 해 처리합니다.
ConnectionFactory는 RabbitMQ와 연결을 유지하며, 수신하는 메시지를 이 연결 을 통해 가져옵니다.
setQueueNames(QUEUE_NAME) 메서드는 특정 큐 이름을 설정. 이 컨테이너는 코드에서 설명한 큐 네임인 helloQueue에서 수신되는 메시지를 모니터링합니다.
setMessageListener(listenerAdapter)는 listenerAdapter를 설정하여, 메시지가 수신될 때 호출할 리스너를 지정합니다.

 

@Bean
public MessageListenerAdapter listenerAdapter(Receiver receiver){
    return new MessageListenerAdapter(receiver, "receiveMessage");
}

 

receiver 객체는 메시지를 처리하는 역할을 하는 Bean이며, receiveMessage 메서드 를 호출합니다.
MessageListenerAdapter는 RabbitMQ에서 수신된 메시지를 특정 메서드에 전달 할 수 있도록 해줍니다
이 경우, receiveMessage 메서드가 자동으로 호출되며, 메시지 내용을 인자로 받습니다
Receiver 클래스의 receiveMessage 메서드가 메시지를 수신하여 처리할 수 있도 록 설정합니다. (RabbitMQ에서 수신된 메시지가 receiver.receiveMessage(String message) 메서드로 전달합니다.)

 

6. Sender 구현

import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Component;

@Component
public class Sender { // 메시지가 전달이 됐을때 RabbitTemplate을 통해 큐에 전달하는

    private final RabbitTemplate rabbitTemplate;

    public Sender(RabbitTemplate rabbitTemplate) {
        this.rabbitTemplate = rabbitTemplate;
    }

    public void send(String message){
        rabbitTemplate.convertAndSend(RabbitMQConfig.QUEUE_NAME, message);
        System.out.println("[#] Sent : " + message);
    }
}

 

RabbitTemplate을 주입받고 메서드를 사용합니다.

 

7. Receiver 구현

import org.springframework.stereotype.Component;

@Component
public class Receiver { // Consumer 역할
    public void receiveMessage(String message){
        System.out.println("[#] Received : " + message);
    }
}

 

Receiver는 Consumer 역할을 하고, 메서드 이름을 Config에서

@Bean
public MessageListenerAdapter listenerAdapter(Receiver receiver){
    return new MessageListenerAdapter(receiver, "receiveMessage");
}

어댑터에 적어준 이름과 같아야 합니다.

 

8. 테스트

적당하게 Controller 하나 만들어 줍니다.

import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api/message")
public class MessageController {
    private final Sender sender;

    public MessageController(Sender sender) {
        this.sender = sender;
    }

    @PostMapping("/send")
    public String sendMessage(@RequestBody String message){
        sender.send(message);
        return "[#] Message sent successfully " + message;
    }
}

 

 

 

 

저는 postman을 이용해서 테스트 햇씁니다.

 

 

 

 

이렇게 날려보면?

 

 

이런 응답을 받았고 콘솔을 확인해보면?

잘 주고받은것 같습니다 이제 rabbitmq 모니터링 페이지에 가서 Queues and Streams 탭에 가보면

 

코드에서 설정한 QUEUE_NAME의 큐 이름으로 큐가 생겨있고 눌러서 들어가보면 위 화면처럼 트래픽을 확인할 수 있고

이것저것 모니터링 할 수 있습니다.

 

이렇게 간단하게 메시지만 주고받는 예제를 해봤습니다. 끝

 

+ Recent posts