목공책 하나 들이셔요~

2014년 9월 8일 월요일

Google Talk로 XMPP 배우기 #3

이 글은 Adarsh Ramamurthy가 작성한 "Fun with XMPP and Google Talk, Part 2"를 기반으로 번역하고 내용을 추가한 것입니다. 원문은 하나의 글이지만 내용이 길어서 이를 둘로 나누었고, 이 글은 그 뒷부분입니다.  원문은 아래 링크를 확인하세요.

http://www.adarshr.com/papers/xmpp2

어플리케이션 개발을 위한 XMPP 라이브러리

XMPP 어플리케이션을 개발하기에 앞서, 쉽게 사용할 수 있는 XMPP 라이브러리들이 있는지 먼저 살펴보는 것이 좋겠습니다. XMPP 라이브러는 여러개 있는데 각각 다른 언어를 지원하며, 또 각기 다른 라이선스 정책을 가지고 있습니다. 다행히도 몇몇 라이브러리들은 무료로 사용할 수 있습니다. 이 라이브러리들은 XMPP의 모든 기능을 구현하고 있을 뿐 아니라, 몇몇 유용한 컴포넌트들을 제공하기도 합니다.



우리가 예제로 사용할 어플리케이션을 개발하기 위해 저는 Smack API를 선택했습니다. Smack은 오픈소스 프로젝트이며 Java로 구현된 XMPP 클라이언트를 위한 라이브러리입니다. API는 이 곳에서 다운로드할 수 있으며, 이 API의 소스코드는 Git를 통해 내려받을 수 있는데 이 곳의 설명을 참조하십시요.

Smack API 사용하기

이제 Smack API를 이용하여 간단한 예제를 작성해 보도록 합시다. 여기서 보여드리는 Java코드는 전체 코드 중에서 중요한 일부분만 발췌한 것입니다. 실제 코드에 사용되기 위해서는 적절한 예외처리와 환경에 따른 설정 등이 추가되어야 합니다.

XMPP 커넥션을 얻고 로스터 항목 알아내기

다음 코드는 Google Talk 서버로 어떻게 연결하고 로스터를 어떻게 가져오는지 보여 줍니다.

    // Create XMPP connection to gmail.com server
    XMPPConnection connection = new XMPPConnection("gmail.com");
    
    try
    {
        // Connect
        connection.connect();
        
        // Login with appropriate credentials
        connection.login("username", "password");

        // Get the user's roster
        Roster roster = connection.getRoster();
        
        // Print the number of contacts
        System.out.println("Number of contacts: " + roster.getEntryCount());

        // Enumerate all contacts in the user's roster
        for (RosterEntry entry : roster.getEntries())
        {
            System.out.println("User: " + entry.getUser());
        }
    }
    catch (XMPPException e)
    {
        // Do something better than this!
        e.printStackTrace();
    }


Google Talk 상태를 프로그램에서 바꾸기

다음의 코드 조각은 당신의 채팅 상태를 프로그램에서 바꾸는 방법을 보여 줍니다. Google Talk은 채팅 상태에서 최고의 우선순위를 갖기 때문에 우리는 단지 프로그램이 실행되는 동안에만 Google Talk의 상태를 변경할 수 있습니다. 그래서 저는 쓰레드를 만들어서 20초마다 한번씩 상태를 변경하는 방식을 사용했습니다. 또한 프로그램에서 상태를 바꿨다고 할 지라도 당신 계정의 Google Talk 클라이언트에서 자신의 채팅 상태가 바뀌지는 않습니다. 제대로 변경되었는지 확인하려면 당신을 친구로 등록한 사람에 물어봐야 합니다.

    // Create the presence object with default availability 
    Presence presence = new Presence(Presence.Type.available);
    
    // Set the status message
    presence.setStatus("Online, Programmatically!");
    
    // Set the highest priority
    presence.setPriority(24);
    
    // Set available presence mode
    presence.setMode(Presence.Mode.available);
    
    // Send the presence packet through the connection
    connection.sendPacket(presence);
    
    // Sleep for 20 seconds
    Thread.sleep(20000);

이런 식으로 Smack API를 이용하여 다양한 일들을 할 수 있습니다. 만일 Smack에 대해 더 알고 싶다면 Smack API 문서를 자세히 읽어보길 권합니다.

Google Talk 상태 메시지를 스크롤하기

당신을 등록한 친구의 Google Talk 클라이언트에 왼쪽 그림처럼 당신의 상태 메시지를 스크롤되게 할 수 있겠습니까?

당신은 프로그램에서 프레전스(Presence)를 어떻게 설정하는지 위 예제를 통해 배웠습니다. 저는 상태 메시지를 "I love Maggi Noodles"라고 바꿉니다. 그리고 글자를 오른쪽으로 한글자씩 이동하면서 스트림에 상태 메시지를 변경하는 패킷을 보냅니다. 그리고 약간의 딜레이를 준 후에 이를 계속 반복하면 스크롤되는 모양을 흉내낼 수 있습니다.

아래 코드는 이를 구현한 것입니다.










    // The text for the status
    String status = "I \u2665 Maggi Noodles ";
    
    // Construct the presence object
    Presence presence = 
        new Presence(
            Presence.Type.available, 
            status, 
            24, 
            Presence.Mode.available);
    
    // Send 500 packets
    for (int i = 0; i < 500; i++)
    {
        // Rotate left by a character
        status = rotate(status);
        
        // Set the status into presence object
        presence.setStatus(status);
        
        // Send it
        connection.sendPacket(presence);
        
        // Sleep for a tenth of a second
        Thread.sleep(100);
    }

rotate() 함수의 코드는 아래와 같습니다.

    // Rotate by shifting a character right at a time
    private static String rotate(String input)
    {
        return input.substring(1) + input.charAt(0);
    }

Winamp로부터 현재 재생 음악을 가져와 표시하기

또 하나의 흥미로운 Google Talk 상태 메시지를 조작하는 예제를 살펴 봅시다. 사실 제가 이 기능을 구현할 때만 해도 Google Talk이 현재 재생하고 있는 음악의 제목을 보여주는 기능을 제공하지 않았습니다. 그래서 직접 만들어야 했는데, 현재는 Google Talk에서 이 기능을 제공하고 있습니다. 하지만 어떻게 프로그래밍 하는지를 배우는게 목적이므로 이 기능을 직접 구현해 보도록 합시다.

현재 재생되고 있는 음악에 대한 정보를 얻으려면 Winamp에 간단한 플러그인을 하나 설치해야 합니다. 이 플러그인의 이름은 "Now Playing Plug-in"이고 여기에서 다운로드 받을 수 있습니다.

이 플러그인은 Winamp에서 재생되고 있는 음악의 제목 혹은 ID3 태그 정보를 세가지 방법으로 외부 프로그램에 전달할 수 있습니다. 그 방법은 FTP, 로컬에 저장, HTTP Post 등입니다. 이 중에서 가장 간단한 HTTP Post 방식을 사용합시다. 이 방식에서 플러그인은 음악이 변경될 때 지정한 HTTP Post를 통해 지정한 URL로 곡목 정보를 보내 줍니다. 그러므로 플러그인에 Post를 받을 URL을 넣어주어야 합니다. 예를 들어 http://localhost:8080/GStatus 식으로 하면 됩니다.


이렇게 설정해 두고 이제 저 Post를 받을 Java 서블릿을 개발하여 Tomcat 같은 서블릿 컨테이너에 배포를 해야 합니다. 플러그인은 Winamp가 재생하는 음악에 대한 정보를 계속해서 그 서블릿에 Post로 올립니다. 예를 들어 음악의 이름인 경우 "Song[0][Title]"이라는 이름의 파라미터에 담깁니다. 다른 값들은 플러그인의 문서를 참조 바랍니다.

아래의 서블릿 코드는 이 과정을 상세히 담고 있습니다. 네트웍 트래픽을 줄이기 위해 커넥션은 서블릿의 init() 함수에서 한번 얻어지고나서 보관됩니다. 비슷하게 커넥션 객체는 서블릿의 destroy() 함수에서 닫을 수 있습니다.

public class GStatus extends HttpServlet
    {
        // We should re-use this
        private XMPPConnection connection;
        
        protected void init() throws ServletException
        {
            super.init();
            
            try
            {
                // Create the connection
                this.connection = new XMPPConnection("gmail.com");
                
                // Connect
                connection.connect();
                
                // Login with appropriate credentials
                this.connection.login("username", "password");
            }
            catch (XMPPException e)
            {
                throw new RuntimeException(e);
            }
        }
        
        protected void doPost(HttpServletRequest request, 
            HttpServletResponse response) 
            throws ServletException, IOException
        {
            // Create the presence object with default availability 
            Presence presence = new Presence(Presence.Type.available);
            
            // Get the Title and Artist of the track now playing
            String title = request.getParameter("Song[0][Title]");
            String artist = request.getParameter("Song[0][Artist]");
            
            // Set the status message
            presence.setStatus(
                "I'm listening to \u266A "
                + artist
                + " - "
                + title);
            
            // Set the highest priority
            presence.setPriority(24);
            
            // Set available presence mode
            presence.setMode(Presence.Mode.available);
            
            // Send the presence packet through the connection
            this.connection.sendPacket(presence);
        }
        
        protected void destroy()
        {
            super.destroy();
            
            // Disconnect the connection
            this.connection.disconnect();
        }
    }

서블릿과 플러그인이 잘 설치되고 설정되었다면 Winamp는 재생하는 곡이 바뀔 때 마다 등록된 URL로 음악에 대한 정보를 HTTP Post로 보낼 겁니다. 서블릿은 HttpServletRequest 객체를 이용하여 전달된 음악에 대한 정보를 얻어냅니다. 그리고 Presence 패킷을 만들어서 미리 얻어진 Google Talk 서버 커넥션으로 보냅니다. 또한 서버는 당신의 로스터에 있는 모든 친구들에게 변경된 상태 메시지를 전역 발송하게 됩니다.

모든 것이 순조롭게 진행된다면 오른쪽과 같이 친구의 Google Talk 클라이언트에 당신의 PC에서 현재 재생되고 있는 음악이 상태 메시지로 표시될 겁니다.

Google Talk 클라이언트 만을 가지고는 이런 일을 할 수 없습니다. 당신은 상태 메시지를 프로그램에서 제어하는 방법을 이용하면 이보다도 더 흥미로운 응용을 할 수 있음을 깨달았을 겁니다.

결론

XMPP가 개방형 표준으로 지속되는 한 앞으로도 많은 어플리케이션들이 개발될 것이고, 이는 사람 대 사람의 통신 뿐 아니라 기계와 기계 간의 통신을 위한 용도로도 사용될 겁니다. 그리고 Jabber와 XMPP라는 용어는 점점 더 동일한 의미로 사용될 겁니다. XMPP 확장이 발전됨에 따라 음성 채팅, 파일 전송, 화상 회의, 이벤트 알림, 게임, 캔버스 드로잉 등의 기능들이 별도의 전용 프로토콜이 아닌 표준의 범주에서 정의될 겁니다.

댓글 없음:

댓글 쓰기