주요글: 도커 시작하기
반응형
메시징 시스템의 개요와 JMS에 대해 알아본다.

메시징 시스템

분산 어플리케이션이 급격히 증가하면서 따라서 이전에 발생하지 않았던 동기화, 안정성, 확장성 그리고 보안 등에서 문제가 발생하기 시작하였다. 이에 대한 한가지 해결책은 메시지를 통해 각 컴포넌트 사이의 결합성(coupling)을 약화시키는 메시징 시스템이다.

메시징 시스템은 안정하고, 확장 가능하고 그리고 유연한 분산 어플리케이션을 제작하기 위해 사용된다. 이 글에서는 일반적인 메시징 시스템에 대한 내용과 메시징 시스템의 종류에 대해서 알아보며, 그런 후 개발자들이 JMS(Java Message Service; 자바 메시지 서비스)를 이용하여 메시지 기반의 어플리케이션을 어떻게 작성할 수 있는지에 대해서 알아본다.

메시징 시스템은 분리된 결합되어 있지 않은 어플리케이션이 비동기적으로 신뢰성있게 통신할 수 있도록 해 준다. 메시징 시스템 아키텍처는 일반적으로 각 컴포넌트 사이의 관계를 클라이언트/서버 모델에서 피어-투-피어(peer-to-peer) 관계로 변경한다. 각각의 피어는 다른 피어에 메시지를 전송할 수 있으며, 또한 다른 피어로부터 메시지를 전달받을 수 있다.

메시징 시스템은 고전적인 분산 컴퓨팅 모델에 비해 더욱 강력한 장점을 제공한다. 먼저, 메시징 시스템은 메시지 소비자(message consumers)와 메시지 생산자(message producer)가 약한 결합성(loose coupling)을 갖도록 한다. 메시지 생산자와 소비자는 서로를 거의 알지 못한다. 메시지 소비자에게 있어서, 그 메시지를 누가 생산했고 생선자가 어디에 있는 지 또는 메시지가 언제 생산되었는지의 여부는 문제가 되지 않는다.

이러한 메시징 시스템의 특징은 동적이고, 신뢰성 있고 유연한 시스템을 구현할 수 있도록 해 주며, 그에 따라 시스템의 나머지 부분에 영향을 않고 하위 어플리케이션의 전체적인 구성을 변경할 수 있다.

메시징 시스템의 또 다른 장점은 높은 확장성, 서로 다른 네트워크 사이의 쉬운 통합 그리고 안정성이다.

메시징 시스템의 안정적이고 확장가능한 특징 때문에, 많은 비지니스와 컴퓨팅 사이언스 문제를 해결하기 위해 메시징 시스템을 사용하고 있다. 예를 들어, 메시징 시스템은 워크플로우, 네트워크 관리, 통신 서비스, 고객 관리, 일기 예보 시스템과 같은 다양한 어플리케이션의 기반이 되고 있다. 또한, 메시징 시스템은 통합이 필연적인 분리된 시스템들을 엮어주는 매개체로서의 중요한 역할을 하고 있다.

메시징 시스템의 종류

일반적으로 사용되는 메시징 시스템의 종류에는 출판/구독(Publish/Subscribe) 방식과 포인트-투-포인트(Point-To-Point) 방식의 두 종류가 있다.

출판/구독(Publish/Subscribe) 방식

출판/구독 메시징 시스템은 메시지의 전송에 참여하고 있는 생산자(producer)와 소비자(consumer)가 이벤트를 사용하여 통신한다. 생산자는 이벤트를 "출판(즉, 발생)"하고 소비자는 자신이 관심을 갖고 있는 이벤트를 "구독"하여 그 이벤트를 소비한다. 생산자는 메시지를 특정한 토픽과 연관시키며, 그 메시지는 그 메시지와 관련된 토픽에 등록한 소비자에게 전달된다.

점대점(Point-To-Point) 방식

점대점(Point-To-Point) 메시징 시스템에서 메시지는 개개의 소비자에게 전달되며, 각각의 소비자는 들어오는 메시지를 저장하는 큐를 갖고 있다. 메시징 어플리케이션은 지정된 큐에 메시지를 보내고, 클라이언트는 큐로부터 메시지를 읽어들인다.

Java Message Service

자바 메시지 서비스는 J2EE(Java 2 Enterprise Edition)의 부분이며, 자바 개발자들이 엔터프라이즈 메시지 시스템의 공통적인 특징에 접근하기 위해 사용할 수 있는 표준 API를 제공한다. JMS는 출판/구독 모델과 포인트-투-포인트 모델을 지원하며, 임의의 자바 객체로 구성된 메시지 타입을 생성할 수 있도록 해 준다.

디자인 목적

JMS의 기본적인 설계 목적은 메시징 시스템의 클라이언트가 하부의 메시징 시스템 프로바이더에 독립적으로 사용할 수 있는 일관된 인터페이스 집합을 제공하는 것이다.

JMS는 머신 아키텍처와 운영체제에 상관없이 클라이언트 어플리케이션이 이식성을 갖도록 해줄 뿐만 아니라, 또한 메시징 제품에 상관없는 이식성을 갖도록 해 준다. JMS로 작성된 클라이언트 애플리케이션은 JMS 호환 메시징 시스템에서 변경할 필요 없이 사용할 수 있다.

JMS는 또한 다음과 같은 목적으로 설계되었다.

  • 메시징 시스템 프로바이더가 그들의 제품을 위해 JMS API를 구현하기 위해 필요한 노력을 최소화시켜준다.
  • 대부분의 일반적인 메시징 시스템 기능을 제공한다.
많은 메시징 시스템 벤더들은 그들의 제품에 맞게 JMS를 구현하였으며, 따라서 자바를 사용하여 시스템의 기능에 접근할 수 있도록 하고 있다.

JMS 클라이언트는 자바의 특징을 사용한다

JMS 클라이언트는 자바를 기반으로 하고 있기 때문에 JDBC, 자바빈 컴포넌트, JNDI, JTA 또는 JavaMail 등의 기존의 존재하는 자바 API를 사용할 수 있다.

JMS의 세부 내용

이제부터 JMS를 사용한 메시징 시스템의 클라이언트를 작성하는 것에 대해서 좀 더 세부적으로 알아보도록 하자. 먼저 알아볼 내용은 메시징 시스템의 가장 기본 요소인 메시지이다.

메시지

메시징 시스템에서 어플리케이션 간의 통신의 핵심은 메시지이며, 따라서 JMS를 사용하는 개발자들은 메시지에 대해 이해하고 있어야 한다. 메시징 시스템에 따라 메시지의 정의가 다양하기 하지만, JMS는 메시지를 설명하고 접근하는 통합된 의미를 사용하고 있다. JMS에서 메시지는 세 부분으로 구성되어 있다.

  • 메시지 헤더:
    메시지를 구분하기 위해 사용된다. 예를 들어, 주어진 메시지가 특정 구독자에게 알맞은 것인지를 판단하기 위해 헤더를 사용한다.
  • 프로퍼티:
    어플리케이션에 특정한 값, 프로바이더에 특정한 값 그리고 추가적인 헤더 필드를 제공하기 위해 사용된다.
  • 몸체:
    메시지의 내용을 저장한다. TestMessage나 ObjectMessage와 같은 다양한 포맷을 지원한다.
TextMessage

TextMessage는 Strign 객체를 감싸고 있다. 이 객체는 단지 문자열만 전송할 때 유용하게 사용할 수 있다. 앞으로 많은 메시징 시스템들이 XML 기반으로 될 것으로 예상되기 때문에, TextMessage는 대부분의 메시징 시스템에서 지원될 것이다.

TextMessage 객체를 생성하는 것은 매우 간단하며, 다음과 같은 두줄만으로 생성할 수 있다.

TextMessage message = session.createMessage();
message.setText("hello world!");

이런 방법으로 생성된 TextMessage 객체는 메시징 시스템에 출판할 준비가 된 것이다.

ObjectMessage

ObjectMessage 객체는 그 이름에서 알 수 있듯이 일반적인 자바 객체를 감싸고 있는 메시지이다. 모든 직렬화가능한 자바 객체를 ObjectMessage로 사용할 수 있다. 만약 하나의 메시지에 다중의 객체를 전송해야 한다면, List나 Set과 같은 콜렉션(Collection)객체를 사용하면 된다. 이 경우, 콜렉션 객체는 직렬화가능한 객체만을 저장하고 있어야 한다.

ObjectMessage 객체는 다음과 같이 생성한다.

ObjectMessage message = session.createObjectMessage();
message.setObject(somObject);

JNDI와 관련해서 알아야 할 점

J2EE의 다른 API와 마찬가지로 JMS는 필요한 자원을 찾기 위해서 JNDI(Java Naming and Directory Interface)를 사용한다. JNDI에 대한 내용은 이 글의 범위를 넘어서므로, JNDI에 대해서 자세히 알고 싶다면 JNDI 홈페이지를 참조하기 바란다.

JMS 클라이언트 작성

일반적은 JMS 클라이언트는 다음의 기본적인 3 단계를 통해서 작성된다.

  1. 메시징 시스템 프로바이더와 연결된 커넥션을 생성한다.
  2. 메시지를 전송하기 받기 위한 세션을 생성한다.
  3. 메시지를 생성하고 받기 위해 MessageProducer와 MessageConsumer를 생성한다.
이 과정을 수행하면, 메시지를 생성하는 클라이언트는 메시지를 생성한 후 특정 주제로 그 메시지를 출판할 수 있다. 반면에 메시지를 소비하는 클라이언트는 자신이 관심을 갖는 주제와 관련된 메시지를 기다리고 있다가 메시지가 도착하면 그것을 소비한다.

실제로 어떻게 이런 것들이 이루어지는 알아보기 위해 출판/구독 메시징 시스템에서 특정 주제와 관련된 메시지를 출판하는 메시지 생산자에 대해 살펴보기로 하자. 좀더 쉽게 알아볼 수 있도록 하기 위해 예외 처리와 관련된 코드는 생략하였다.

메시징 시스템 프로바이더에 연결하기

커넥션(Connection)은 클라이언트가 하부의 메시징 시스템에 접근할 수 있도록 해 주며, 자원 할당과 관리를 수행한다. ConnectionFactory를 사용하여 커넥션을 생성한다. ConnectionFactory는 일반적으로 JNDI를 사용하여 위치시킨다.

다음 코드는 커넥션 생성 단계와 관련된 부분을 보여주고 있다.

Context messaging = new InitialContext();
// JNDI 콘텍스트를 구한다.
TopicConnectionFactory topicConnectionFactory = 
        (TopicConnectionFactory)messaging.lookup("TopicConnectionFactory");
TopicConnection topicConnection =
       topicConnectionFactory.createTopicConnection();

세션 생성

세션은 메시지 생산과 소비를 위한 콘텍스트를 제공하는 경량의 JMS 객체이다. 메시지 생산자와 소비자를 생성할 때 세션을 사용하여 또한 메시지를 생성할 때에도 세션을 사용한다.

TopicSession session =
     topicConnection.createTopicSession(false, Session.CLIENT_ACKNOWLEDGE);

createTopicSession() 메소드에 전달되는 두 파라미터는 각각 트랜잭션과 메시지 인식을 제어한다.

토픽 지정

토픽(주제, 그룹 또는 채널이라고도 한다)은 JNDI를 통해서 위치시킬 수 있다. 토픽은 전송되거나 수신된 메시지를 분류한다. 출판/구독 시스템에서, 구독자는 주어진 토픽을 구독하며, 출판자는 그들이 출판한 메시지를 특정한 토픽과 연관시킨다.

다음은 "StockData"라고 불리는 토픽을 생성하는 코드를 보여주고 있다.

Topic stockTopic = messaging.lookup("StockData");

커넥션 시작

위의 과정을 거치는 동안에 메시지의 흐름은 초기화하는 동안에 예측할 수 없는 행동을 하지 못하도록 하기 위해 억제된다. 일단 초기화가 끝나면, 커넥션은 반드시 메시지 이름을 시작해야 한다.

topicConnection.start();

메시지 생산자 생성

출판/구독 시스템에서, 생산자는 주어진 토픽에 메시지를 출판한다. 다음 코드는 출판자를 생성하고 이어서 간단한 텍스트 메시지를 출판하는 것을 보여주고 있다.

TopicPublisher publisher =
     session.createPublisher(stockTopic);
TextMessage message = session.createMessage();
message.setText("kosdaq: 101");

publisher.publish(message);

비슷한 과정을 통해서 구독자를 생성할 수 있으며, 또한 점대점 시스템을 위한 JMS 클라이언트를 생성할 수 있다.

결론

이 글에서는 메시징 기반의 어플리케이션을 작성하기 위해 JMS를 사용하는 것과 관련된 기본적인 개념에 대해서 살펴보았다. JMS 호환 시스템의 목록은 "JMS 호환 벤더 목록"을 참고하기 바란다.

관련링크:

+ Recent posts