> For the complete documentation index, see [llms.txt](https://wannaqueen.gitbook.io/spring5/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://wannaqueen.gitbook.io/spring5/spring-boot/undefined-1/34./34.1-jms.md).

# 34.1 JMS by sh

{% hint style="info" %}
JMS

* **메시지 큐를 지원하는 J2EE의 메시지 처리 API**

  * 자바 전용이라 AMQP는 지원하지 않는다.

메시지 큐

* **MOM을 구현한 시스템** (웹 서버의 성능을 고려한 **비동기 메시지 처리** 방식)
  * MOM (= Message Oriented Middleware) : 분산 시스템 간 메시지를 주고 받는 기능을 지원하는 소프트웨어나 하드웨어 인프라
    {% endhint %}

{% hint style="info" %}
JMS 주요 개념

* **Message Broker** : 목적지에 안전하게 메시지를 건네주는 중개자 역할
* **Destination** : 목적지에 배달될 2가지 메시지 모델 QUEUE, TOPIC
  * Queue : Point to Point (Consumer는 메시지를 받기 위해 경쟁)
  * Topic : Publish to Subscribe
    {% endhint %}

**`javax.jms.ConnectionFactory` 인터페이스는 JMS 브로커와 상호 작용하기 위한 `javax.jms.Connection`을 만드는 표준 방법을 제공합니다.** Spring은 JMS와 연동하기 위해 `ConnectionFactory`가 필요하지만 일반적으로 직접 사용하지 않아도 되며 상위 수준의 메시징 추상화에 의존 할 수있습니다. (자세한 내용은 Spring Framework 참조 문서의  the[relevant section](https://docs.spring.io/spring/docs/5.1.7.RELEASE/spring-framework-reference/integration.html#jms)을 참조하십시오.) Spring Boot는 또한 메시지를 보내고 받기 위해 필요한 인프라를 자동으로 구성합니다.&#x20;

### 34.1.1 ActiveMQ 지원

{% hint style="info" %}
ActiveMQ

* 클라이언트 간 메시지를 송수신 할 수 있는 오픈 소스 브로커 (JMS 서버), MOM(메시지 지향 미들웨어)이다.

메시지 처리 구조?
{% endhint %}

![](/files/-LhLoEYe4tqx-W3q9roJ)

{% hint style="info" %}
기본적으로 메시지를 생산하는 Producer, activeMQ Broker(Server), 메시지를 소비하는 Consumer로 구성되어 있다.

* Queue 모델의 경우 메시지를 받는 Consumer가 다수일 때 연결된 순서로 메시지 제공됨

  * 생성자로부터 단일 사용자에게 전달된다.&#x20;

* Topic 모델의 경우 메시지를 받는 Consumer가 다수일 때 모두에게 메시지 제공됨
  * 단일 생성자가 사용자의 수 제한 없이 메시지를 전달한다.&#x20;
    {% endhint %}

**classpath에서** [**ActiveMQ**](https://activemq.apache.org/)**를 사용할 수 있으면, Spring Boot는 `ConnectionFactory`를 설정할 수도 있습니다. 브로커가 있으면 내장 브로커가 자동으로 시작되고 구성됩니다** (구성을 통해 브로커 URL을 지정하지 않은 경우).&#x20;

| ![\[Note\]](https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/images/note.png)                       |
| ----------------------------------------------------------------------------------------------------------------------- |
| **`spring-boot-starter-activemq`**&#xB97C; 사용하면 JMS와 통합할 Spring 인프라와 마찬가지로 ActiveMQ 인스턴스를 연결하거나 포함시키는 데 필요한 종속성이 제공됩니다. |

ActiveMQ 구성은 **`spring.activemq.*`**&#xC758; 외부 구성 등록 정보에 의해 제어됩니다. 예를 들어 다음 섹션을 `application.properties`로 선언 할 수 있습니다.&#x20;

```
spring.activemq.broker-url=tcp://192.168.1.210:9876
spring.activemq.user=admin
spring.activemq.password=secret
```

기본적으로 `CachingConnectionFactory`는 고유한 `ConnectionFactory`를 외부 구성 속성들에 의해 `spring.jms.*`로 제어 할 수있는 적절한 설정으로 래핑합니다.&#x20;

```
spring.jms.cache.session-cache-size=5
```

네이티브 풀링을 사용하려면 다음 예제와 같이 `org.messaginghub:pooled-jms`에 종속성을 추가하고 `JmsPoolConnectionFactory`를 구성하여 그렇게 할 수 있습니다&#x20;

```
spring.activemq.pool.enabled=true
spring.activemq.pool.max-connections=50
```

| ![\[Tip\]](https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/images/tip.png)                                                                                                                                                                                                                                                |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 지원되는 옵션에 대해서는 [`ActiveMQProperties`](https://github.com/spring-projects/spring-boot/tree/v2.1.5.RELEASE/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/activemq/ActiveMQProperties.java)를 참조하십시오. 고급 사용자 정의를 위해 `ActiveMQConnectionFactoryCustomizer`를 구현하는 임의의 수의 Bean을 등록 할 수도 있습니다. |

기본적으로 ActiveMQ는 목적지가 아직 존재하지 않는 경우 목적지를 작성하여 목적지가 제공된 이름에 대해 해석되도록합니다.&#x20;

### 34.1.2 Artemis 지원

**Spring Boot는 클래스 패스에서** [**Artemis**](https://activemq.apache.org/artemis/)**를 사용할 수 있음을 감지하면 `ConnectionFactory`를 자동으로 구성 할 수 있습니다. 브로커가 있으면 내장 된 브로커가 자동으로 시작되고 구성됩니다** (mode 등록 정보가 명시적으로 설정되어 있지 않은 경우). **지원되는 모드는 `embedded`**(내장된 브로커가 필요하며 브로커를 클래스 경로에서 사용할 수 없는 경우 오류가 발생하도록 명시하는)**와 `native`**(`netty`전송 프로토콜을 사용하여 브로커에 연결하는)입니다. 후자가 구성되면 스프링 부트는 기본 설정으로 로컬 시스템에서 실행 중인 브로커에 연결하는 `ConnectionFactory`를 구성합니다.&#x20;

| ![\[Note\]](https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/images/note.png)                                                                                             |
| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **`spring-boot-starter-artemis`**&#xB97C; 사용하면 JMS와 통합 할 Spring 인프라뿐만 아니라 기존 Artemis 인스턴스에 연결하는 데 필요한 종속성이 제공됩니다. 애플리케이션에 `org.apache.activemq:artemis-jms-server`를 추가하면 임베디드 모드를 사용할 수 있습니다. |

Artemis 구성은 **`spring.artemis.*`**&#xC758; 외부 구성 등록 정보에 의해 제어됩니다. 예를 들어 다음 섹션을 `application.properties`로 선언 할 수 있습니다.

```
spring.artemis.mode=native
spring.artemis.host=192.168.1.210
spring.artemis.port=9876
spring.artemis.user=admin
spring.artemis.password=secret
```

브로커를 임베드 할 때 지속성을 활성화 할 것인지 선택할 수 있으며 사용 가능하게 할 대상을 나열 할 수 있습니다. 이것들은 쉼표로 구분 된 목록으로 지정하여 기본 옵션으로 만들거나 `org.apache.activemq.artemis.jms.server.config.JMSQueueConfiguration` 또는 `org.apache.activemq.artemis.jms.server.config.TopicConfiguration`타입의 bean을 정의 할 수 있습니다. 이것들은 각각 고급 큐 및 주제 구성 각각에 대해 설명합니다.

기본적으로 `CachingConnectionFactory`는 고유 한 `ConnectionFactory`를 외부 구성 등록 정보 인 `spring.jms.*`로 제어 할 수있는 적절한 설정으로 래핑합니다.

```
spring.jms.cache.session-cache-size=5
```

네이티브 풀링을 사용하려면 다음 예제와 같이 `org.messaginghub:pooled-jms`에 종속성을 추가하고 `JmsPoolConnectionFactory`를 구성하여 그렇게 할 수 있습니다.&#x20;

```
spring.artemis.pool.enabled=true
spring.artemis.pool.max-connections=50
```

지원되는 옵션에 대해서는 [`ArtemisProperties`](https://github.com/spring-projects/spring-boot/tree/v2.1.5.RELEASE/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/artemis/ArtemisProperties.java)를 참조하십시오.

JNDI 조회가 필요 없으며 대상은 Artemis 구성의 `name`속성 또는 구성을 통해 제공된 이름을 사용하여 이름에 대해 확인됩니다.&#x20;

### 34.1.3 JNDI ConnectionFactory 사용&#x20;

응용 프로그램 서버에서 **응용 프로그램을 실행하는 경우 Spring Boot는 JNDI를 사용하여 JMS `ConnectionFactory`를 찾으려고 시도합니다.** 기본적으로 `java:/JmsXA` 및 `java:/XAConnectionFactory` 위치가 검사됩니다. 다음 예제와 같이 대체 위치를 지정해야하는 경우 `spring.jms.jndi-name` 등록 정보를 사용할 수 있습니다.

```
spring.jms.jndi-name=java:/MyConnectionFactory
```

{% hint style="info" %}
JMS 프로그래밍 모델에서 사용되는 2가지 객체

1\. 연결 팩토리 객체 : 공급자가 메시지 전달 시 사용하는 프로토콜 및 메커니즘에 따라 동작이 달라지는 연결을 작성하는 데 사용&#x20;

2\. 대상 객체 : 브로커의 물리적 대상의 이름을 지정하는 데 사용. 메시지 서버에 있는 물리적 대상의 특정 이름 지정 규약 및 기능에 따라 다르다.

* **JMS 관리 대상 객체**&#x20;
  * **관리자가 작성 및 구성하고 JNDI 이름 영역(객체 저장소)에서 저장하며 클라이언트가 표준 JNDI 조회 코드를 통해 액세스한다.** (공급자 별 객체 조회, 참조할 때 논리적 이름 사용)
    {% endhint %}

### 34.1.4 메시지 전송&#x20;

**Spring의 `JmsTemplate`은 자동으로 구성되어 있으므로 다음 예제와 같이 직접 bean에 autowire 할 수 있습니다.**

{% hint style="info" %}
JmsTemplate

* 스프링에서 JMS 메시징을 사용하는 핵심 컴포넌트 (동기적으로 메시지를 받거나 보내는 데 사용)

<https://starplatina.tistory.com/entry/JMS-2>
{% endhint %}

```java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.stereotype.Component;

@Component
public class MyBean {

	private final JmsTemplate jmsTemplate;

	@Autowired
	public MyBean(JmsTemplate jmsTemplate) {
		this.jmsTemplate = jmsTemplate;
	}

	// ...

}
```

| ![\[Note\]](https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/images/note.png)                                                                                                                                                           |
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [`JmsMessagingTemplate`](https://docs.spring.io/spring/docs/5.1.7.RELEASE/javadoc-api/org/springframework/jms/core/JmsMessagingTemplate.html)도 비슷한 방식으로 주입 할 수 있습니다. `DestinationResolver`또는 `MessageConverter`bean이 정의되면 자동 구성된 `JmsTemplate`에 자동으로 연관됩니다. |

###

### 34.1.5 메시지 수신&#x20;

**JMS 인프라가 존재할 때 모든 Bean에 `@JmsListener`주석을 달아 리스너 엔드 포인트를 작성할 수 있습니다.** `JmsListenerContainerFactory`가 정의되어 있지 않은 경우, 디폴트의 `JmsListenerContainerFactory`가 자동적으로 설정됩니다. `DestinationResolver`또는 `MessageConverter`bean이 정의되면, 디폴트 팩토리에 자동으로 연관됩니다.

**기본적으로 기본 팩토리는 트랜잭션입니다. `JtaTransactionManager`가있는 인프라에서 실행하면 기본적으로 리스너 컨테이너에 연결됩니다.** 그렇지 않으면 `sessionTransacted`플래그가 사용됩니다. 후자의 경우 리스너 메소드 (또는 그 대리자)에 `@Transactional`을 추가하여 로컬 데이터 저장소 트랜잭션을 수신 메시지 처리에 연결할 수 있습니다. 이렇게하면 로컬 트랜잭션이 완료되면 수신 메시지가 확인됩니다. 여기에는 동일한 JMS 세션에서 수행 된 응답 메시지를 보내는 작업도 포함됩니다.

{% hint style="info" %}
JMS 작업을 하나의 트랜잭션 안에서 동작하게 하려면 서버가 제공하는 트랜잭션 매니저를 JTA를 통해 사용해야 함.&#x20;
{% endhint %}

다음 구성 요소는 `someQueue`대상에 리스너 끝점을 만듭니다.

```java
@Component
public class MyBean {

	@JmsListener(destination = "someQueue")
	public void processMessage(String content) {
		// ...
	}

}
```

| ![\[Tip\]](https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/images/tip.png)                                                                |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 자세한 내용은 [the Javadoc of `@EnableJms`](https://docs.spring.io/spring/docs/5.1.7.RELEASE/javadoc-api/org/springframework/jms/annotation/EnableJms.html)을 참조하십시오. |

**더 많은 `JmsListenerContainerFactory`인스턴스를 생성해야하거나 기본값을 덮어 쓰려면 Spring Boot는 자동 구성 된 것과 동일한 설정으로 `DefaultJmsListenerContainerFactory`를 초기화하는 데 사용할 수있는 a`DefaultJmsListenerContainerFactoryConfigurer`를 제공합니다.**

예를 들어, 다음 예제는 특정 `MessageConverter`를 사용하는 다른 팩토리를 노출합니다.&#x20;

```java
@Configuration
static class JmsConfiguration {

	@Bean
	public DefaultJmsListenerContainerFactory myFactory(
			DefaultJmsListenerContainerFactoryConfigurer configurer) {
		DefaultJmsListenerContainerFactory factory =
				new DefaultJmsListenerContainerFactory();
		configurer.configure(factory, connectionFactory());
		factory.setMessageConverter(myMessageConverter());
		return factory;
	}

}
```

다음과 같이 `@JmsListener`-annotated 메서드에서 팩토리를 사용할 수 있습니다.&#x20;

```java
@Component
public class MyBean {

	@JmsListener(destination = "someQueue", containerFactory="myFactory")
	public void processMessage(String content) {
		// ...
	}

}
```
