도래울

XMPP(Extensible Messaging and Presence Protocol) 소개 본문

IT

XMPP(Extensible Messaging and Presence Protocol) 소개

도래울 2016. 2. 5. 13:36

IM(Instant messaging)은 일반적인 인터넷 사용자뿐만 아니라 비즈니스 사용자에게도 유명한 애플리케이션이다. 이 애플리케이션을 사용하면 다른 사용자와 실시간으로 통신할 수 있을 뿐 아니라 다른 사용자의 상태 정보(사용 가능, 자리 비움, 오프라인 등)도 확인할 수 있다. 초기 오픈 IM 프로토콜 중에는 Jeremie Miller에 의해 개발되어 1998년에 비표준 IM 프로토콜로 시작한 Jabber가 있다. XML을 기반으로 하는 확장 가능한 프로토콜인 Jabber는 다른 애플리케이션을 일반적인 전송 또는 MoM(message-oriented middleware)으로 빠르게 찾아낸다. 결과적으로 XMPP는 이러한 Jabber를 토대로 하여 RFC 3920, "Extensible Messaging and Presence Protocol(XMPP)"이라는 IETF 작업 그룹 프로토콜 문서 형식의 표준 기반 프로토콜이 되었다.

자주 사용하는 약어

  • API: Application programming interface
  • EVA: Extra Vehicular Activity
  • IETF: Internet Engineering Task Force
  • HTTP: Hypertext Transfer Protocol
  • RFC: Request for comments
  • RPC: Remote procedure call
  • SMTP: Simple Mail Transport Protocol
  • SOAP: Simple Object Access Protocol
  • TCP: Transmission Control Protocol
  • URL: Uniform Resource Locator
  • XML: Extensible Markup Language

범용 메시징 전송 프로토콜에는 XMPP만 있는 것이 아니다. XML-RPC 및 SOAP와 같은 다른 유명한 프로토콜에서도 함수 호출 형태의 시맨틱을 사용하여 이 기능을 제공할 수 있다. ReST(Representational State Transfer)와 같은 새로운 메소드는 URL을 사용하여 위치, 오브젝트 및 메소드를 지정할 수 있는 관리되는 파일 액세스를 제공한다.

XMPP 아키텍처

XMPP는 SMTP 등의 다른 애플리케이션 계층 프로토콜과 유사한 아키텍처를 가지고 있다. 이러한 아키텍처에서는 고유한 이름을 가지고 있는 클라이언트가 연관된 서버를 통해 고유 이름을 사용하여 다른 클라이언트와 통신한다. 각 클라이언트는 프로토콜의 클라이언트 양식을 구현하고 서버에서는 라우팅 기능을 제공한다. 그림 1에서는 이 간단한 아키텍처를 보여 준다. 이 경우에는 각 클라이언트가 같은 도메인(discovery.nasa.guv)에 속해 있다.


그림 1. 하나의 서버와 두 개의 클라이언트로 구성된 간단한 XMPP 아키텍처

또한 서버는 도메인 간(예: discovery.nasa.guv와 europa.nasa.guv 간) 라우팅을 위해 통신할 수 있다. 그리고 게이트웨이에서는 외부 메시징 도메인 및 프로토콜 간의 변환 기능을 제공한다. 그림 2의 예제에서는 SMS(Short Message Service) 도메인과 SMTP 도메인에 대한 게이트웨이가 있는 XMPP 네트워크를 보여 준다. 게이트웨이는 이 컨텍스트에서 IM 프로토콜 간의 변환(예: XMPP를 IRC(Internet Relay Chat]로 변환)을 수행하는 데 가장 많이 사용된다. 확장 가능한 프로토콜인 XMPP는 다양한 엔드포인트 프로토콜 간의 보편적인 연결을 제공하는 이상적인 백본 프로토콜이다. XMPP 게이트웨이를 사용하면 지정된 클라이언트-투-서버 세션을 종료하고 대상 엔드포인트 프로토콜에 대한 새 세션을 시작할 수 있다(필요한 프로토콜 변환과 함께).


그림 2. XMPP 게이트웨이가 포함된 형태의 좀 더 복잡한 XMPP 아키텍처


XMPP의 주소

XMPP의 주소(또는 JID[Jabber ID])는 표준 이메일 주소와 비슷하지만 몇 가지 눈에 띄는 차이가 있다. JID에는 선택적 노드, 도메인 및 선택적 리소스가 다음 형식으로 포함되어 있다.

[ node "@" ] domain [ "/" resource ]


이 주소는 이메일 주소처럼 IM 사용자를 정의할 때 가장 일반적으로 사용된다(예: DavidBowman@discovery.nasa.guv). 사용자는 XMPP 서버에 여러 번 로그인할 수 있으며, 이 경우 리소스를 사용하여 위치를 지정할 수 있다. 예를 들어, 동일한 사용자가 기본 터미널에 대한 JID(DavidBowman@discovery.nasa.guv/terminal)와 EVA pod에 대한 또 다른 JID(세션, DavidBowman@discovery.nasa.guv/eva_pod1)를 사용할 수 있다. 따라서 특정 위치를 대상으로 지정할 수 있으며 사용자가 우연히 로그인한 위치로 연결하기 위해 비워 둘 수도 있다.


XMPP 프로토콜

XMPP는 XML 메시지를 사용하여 TCP 소켓 상에서 발생하는 비교적 단순한 프로토콜이다. 비동기 통신이 XML 스트림 내에서 XML 스탠자(stanza)를 통해 발생한다. XML 스트림은 두 엔터티 간에 발생하는 XML 정보 교환을 캡슐화하는 엔벨로프이다. XML 스트림은 정보의 개별 단위인 XML 스탠자를 주고 받는다. 예를 들어, XML 스탠자는 XMPP 내에서 메시지(IM 사용자 간 텍스트)와 현재 상태 정보를 주고 받는 데 사용된다. 두 클라이언트가 XMPP를 사용하여 서로 IM 통신을 수행하는 모습을 보여 주는 아래의 간단한 예제를 보면 이러한 개념을 쉽게 이해할 수 있다.

그림 3에서는 두 엔터티 간의 간단한 통신 내용을 보여 준다. 이 통신을 위해서는 적어도 하나의 서버가 있어야 한다는 점에 유의해야 한다. 이 경우에는 두 클라이언트가 모두 같은 도메인에 속해 있기 때문에 정확히 하나의 서버만 있다. 그림 3에서 왼쪽 클라이언트를 시작 엔터티(두 엔터티 간의 XMPP 통신을 시작하는 엔터티)라고 한다. 이 XML 스트림에서는 to 속성을 사용하여 수신 도메인을 식별하고 XML 네임스페이스를 정의한다. 오른쪽에 있는 수신 클라이언트는 이 XML 스트림을 수신한 후 XML 스트림 응답을 통해 응답한다(이 경우에는 from 특성 사용). 이 단계에서 인증 및 암호화와 같은 여러 다양한 협상이 수행될 수 있다. 하지만 이러한 특성과 IM 클라이언트가 별개의 도메인에 속해 있는 서버-투-서버 통신에 대해서는 이 기사에서 다루지 않는다. (그림 3의 텍스트 전용 버전 참조.)


그림 3. 샘플(단순화된) XMPP 통신 

그림 3에서 설명하는 XML 스트림의 다음 단계는 메시지를 통신하는 것이다. 이 통신은 메시지 스탠자 내에서 발생하며 소스 및 대상 XMPP 주소(from 및 to), 사용 언어 및 스탠자의 본문 내에 포함된 메시지 등을 포함한다. 상대측에서는 고유 메시지를 사용하여 응답하며 주요 차이점은 소스 및 대상 XMPP 주소이다. 마지막으로 연결의 양측에서 발생하는 스트림 종료 메시지를 통해 XML 스트림이 닫힌다.

양쪽 어느 쪽에서나 아래 정의된 것과 같은 오류를 리턴할 수 있다. 이 경우에는 상대측에서 올바르지 않은 XML 스트림 또는 스탠자를 보냈다.

<stream:error>
  <xml-not-well-formed xmlns='urn:ietf:params:xml:ns:xmpp-streams'/>
<stream:error>


이 예제에서 설명한 IM 통신이 간단하기는 하지만 상대측 협상의 보안 특성에 대한 피기백을 통해 메시지 스탠자를 RPC 메시지로 쉽게 변환할 수 있다는 것을 알 수 있다. 도메인 내의 사용자 대신 함수를 노드로 등록하여 동적 웹 서비스 프레임워크를 빌드할 수 있다. 이제 XMPP 간에 통신하는 간단한 애플리케이션을 빌드하는 방법을 살펴보자.


Ruby를 사용한 XMPP 예제

XMPP 라이브러리 선택하기

XMPP의 또 다른 흥미로운 특징으로는 다양한 언어를 포함한 수많은 라이브러리를 선택할 수 있다는 것이다. 이 예제에서는 Ruby 언어와 XMPP4R 라이브러리를 사용한다. 참고자료에서 지원되는 다양한 라이브러리에 대한 링크를 확인할 수 있다.

라이브러리를 통한 XMPP를 확인하기 위해 기술 사전 기능을 제공하는 간단한 IM 에이전트를 개발하는 예제를 살펴보자. 이 예제에서는 표준 인스턴트 메신저를 통해 단어를 입력하면 IM 에이전트가 해당 정의를 리턴한다.

이 예제에서는 XMPP를 통해 다른 IM 에이전트에 연결한 후 단어에 대한 정의를 확인한다. Listing 1에서는 간단한 XMPP 에이전트를 보여 준다.


Listing 1. 단어 정의를 위한 간단한 XMPP 에이전트

require 'xmpp4r/client'

# Create a *very* simple dictionary using a hash
hash = {}
hash['ruby'] = 'Greatest little object oriented scripting language'
hash['xmpp4r'] = 'Simple XMPP library for ruby'
hash['xmpp'] = 'Extensible Messaging and Presence Protocol'

# Connect to the server and authenticate
jid = Jabber::JID::new('bot@default.rs/Home')
cl = Jabber::Client::new(jid)
cl.connect
cl.auth('password')

# Indicate our presence to the server
cl.send Jabber::Presence::new

# Send a salutation to a given user that we're ready
salutation = Jabber::Message::new( 'hal@default.rs', 'DictBot ready' )
salutation.set_type(:chat).set_id('1')
cl.send salutation 

# Add a message callback to respond to peer requests
cl.add_message_callback do |inmsg|

    # Lookup the word in the dictionary
    resp = hash[inmsg.body]
    if resp == nil
      resp = "don't know about " + inmsg.body
    end

    # Send the response
    outmsg = Jabber::Message::new( inmsg.from, resp )
    outmsg.set_type(:chat).set_id('1')
    cl.send outmsg

end

# Run
while 1
end


Listing 1에서는 먼저 간단한 사전을 작성한다. 이를 위해 Ruby의 hash 클래스를 사용하게 된다. 이 클래스를 사용하면 키-값 쌍(배열로 표시됨)을 작성할 수 있으며, 작성 후에는 키를 사용하여 키-값 쌍을 쉽게 참조할 수 있다. 그런 다음 XMPP4R 라이브러리를 사용하여 서버에 연결하게 되는데 이를 위해 먼저 JID를 작성한 후 Client 클래스를 사용하여 새 클라이언트 연결을 작성한다. IM 서버에 실제로 연결하기 위해 connect 메소드를 사용한다. 연결이 설정된 후에는 auth 메소드를 암호와 함께 호출한다. 이제 메시징을 위한 연결이 준비되었다.

다음 단계는 선택적인 단계로 IM 서버에 사용자의 현재 상태를 알리는 것이다. 이를 수행하기 위해 사용자의 현재 상태 스탠자를 서버에 보낸다. 그리고 사용 가능한 상태임을 알리는 선택적 메시지를 상대측에 보낸다. 이를 수행하기 위해 메시지 스탠자를 작성한 후 상대측 주소와 메시지를 사용하여 메시지 스탠자를 초기화한다. 메시지를 초기화한 후에는 Client 클래스 인스턴스와 send 메소드를 사용하여 메시지를 보낸다.

수신된 메시지를 처리하기 위해 클라이언트 연결의 add_message_callback 메소드를 사용한다. 메시지가 수신될 때마다 해당 코드 블록이 호출되면서 메시지를 처리한다. 수신 메시지는 inmsg(Message 인스턴스)로 표현된다. 먼저 수신 메시지의 body에 정의된 단어가 사전에 있는 단어인지 확인한다. nil이 리턴된 경우에는 단어가 없는 것이므로 기본 응답을 제공한다. 수신 메시지의 소스(inmsg.from)와 응답 문자열을 사용하여 새 메시지를 생성한다. 초기화가 완료되면 클라이언트 인스턴스를 통해 새 메시지를 요청자에게 보낸다.

그림 4에서는 애플리케이션의 샘플 실행을 보여 준다. 이 예제에서는 유명한 유니버설 채팅 클라이언트를 사용한다. pidgin 클라이언트는 주요 채팅 프로토콜을 모두 지원하며 여러 채팅 네트워크와 함께(심지어는 동시에) 사용할 수 있다. 그림 4에서는 IM 에이전트가 서버에 연결되어 정의된 사용자와 대화를 시작할 때 작성된 메시징 팝업 창을 보여 준다.


그림 4. 샘플 IM 세션 및 IM 에이전트

이 애플리케이션은 매우 단순하지만 XMPP4R에는 계정 등록, 검색, 파일 전송, 다중 사용자 채팅, 게시/가입, RPC 등의 다양한 기능을 지원하는 여러 가지 클래스와 메소드가 있다. 참고자료에서 모든 XMPP4R 파일, 클래스 및 메소드를 쉽게 볼 수 있는 방법을 제공하는 "탐색 가능한" 클래스 API를 찾을 수 있다.


XMPP의 응용 분야

XMPP는 네트워크를 통한 메시징을 위한 일반적인 프레임워크를 제공한다. 물론 이 프레임워크는 기존 IM 및 현재 상태 데이터 배포 이외의 다른 여러 분야에서도 활용할 수 있다.

IM과 비슷한 응용 분야로는 그룹 또는 다자간 메시징이나 다중 사용자 대화방 개발이 있다. 다자간 통신을 사용하면 Twitter에서 제공하는 마이크로 블로그와 비슷한 기능을 구현할 수 있다. 하지만 XMPP를 통해서는 텍스트를 포함한 다양한 유형의 데이터를 전송할 수 있으며 오디오, 이미지 및 비디오 데이터를 포함한 다양한 형식의 통신이 가능하다.

Bonjour, Service Location Protocol 등과 같은 여러 가지 서비스 검색 프로토콜이 있기는 하지만 XMPP는 네트워크에서 서비스를 검색하는 기능과 서비스 및 기능에 대한 알림 기능을 제공할 수 있는 견고한 토대를 제공한다.

온라인 게임에서도 XMPP를 활용할 수 있다. XMPP는 기본적으로 인증, 현재 상태 정보, 채팅 및 게임 상태 정보에 대한 확장 가능한 실시간 통신을 비롯하여 온라인 게임에 필수적으로 필요한 여러 가지 기능을 제공한다.

마지막으로 XMPP는 클라우드 컴퓨팅의 새 시대를 위한 완벽한 프로토콜이다. 클라우드 컴퓨팅 및 스토리지 시스템에서는 시스템 간에 메시지를 교환하여 상태 정보를 전달하는 작업부터 스토리지 또는 가상 시스템과 같은 대형 오브젝트의 마이그레이션하는 작업까지 다양한 레벨 및 다양한 형식의 통신이 수행된다. 또한 인증 및 전송 데이터 보호 분야에서도 XMPP를 다양한 레벨에서 적용할 수 있으며 특히 미들웨어 프로토콜로 사용하는 것이 이상적이다.

여기서 주목할 점은 대부분의 응용 분야가 사용자 통신과는 관련이 없고 대신 시스템 통신(MMI 또는 시스템 간 통신)과 관련된다는 것이다. 바로 이러한 특징으로 인해 IM용 프로토콜이 다양한 분야에서 사용될 수 있는 것이다.


다중 언어 XMPP

XMPP는 XMPP 기능을 애플리케이션에 제공하는 라이브러리 세트로 구현된다. XMPP에서 현재 지원되는 다양한 언어를 보면 XMPP가 얼마나 유용한 프로토콜인지 쉽게 알 수 있다. CC++ 등의 일반적인 언어를 위한 XMPP 라이브러리 소프트웨어뿐만 아니라 Ruby, Java™ 언어, Python, Perl, Tcl 등의 유명한 스크립트 언어를 위한 XMPP 라이브러리를 찾을 수 있다. 또한 Erlang, C# 및 Lisp와 같은 언어를 지원하는 XMPP 라이브러리도 제공된다. 따라서 어느 환경에서 작업하더라도 현재의 환경에서 사용할 수 있는 XMPP 라이브러리를 통해 XMPP 액세스를 얻을 수 있다. 참고자료에서 다양한 XMPP 라이브러리에서 지원되는 언어 목록을 볼 수 있다.

Comments