본문 바로가기

server

STOMP를 활용한 실시간 채팅 프로그래밍

이번 포스팅은 저번 포스팅 끝에 말 한 STOMP를 활용한 실시간 채팅 프로그래밍을 해보려 한다.

STOMP에 대한 설명은 전에 설명했기 때문에 바로 예제로 들어가 보자.

 

프로젝트 구성부터 알아보자.

 

다음과 같은 프로젝트 구성을 가져갔으며 클래스를 하나씩 확인해 보자.

 

Greeting

package com.example.socket.webSocket;

import lombok.Getter;

@Getter
public class Greeting {
    private String content;

    public Greeting(){

    }

    public Greeting(String content){this.content = content;}

    public String getContent(){return content;}
}

 

HelloMessage

package com.example.socket.webSocket;

import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class HelloMessage {
    private String name;
    private String message;

    public HelloMessage(){

    }

    public HelloMessage(String name, String message) {
        this.name = name;
        this.message = message;
    }
}

 

GreetingController

package com.example.socket.webSocket;

import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.stereotype.Controller;
import org.springframework.web.util.HtmlUtils;

@Controller
public class GreetingController {
    @MessageMapping("/hello")
    @SendTo("/topic/greetings")
    public Greeting greeting(HelloMessage message) throws Exception {
        Thread.sleep(500); // simulated delay
        return new Greeting(HtmlUtils.htmlEscape(message.getName()) + ": " + HtmlUtils.htmlEscape(message.getMessage()));
    }
}

 

WebSocketConfig

package com.example.socket.webSocket;

import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.stereotype.Controller;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.enableSimpleBroker("/topic");
        config.setApplicationDestinationPrefixes("/app");
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/app/gs-guide-websocket").withSockJS();
    }
}

 

각 클래스들에 대해서 확인을 했다면 다음은 스크립트와 html도 확인해 보자.

 

index.html

<!DOCTYPE html>
<html>
<head>
    <title>Hello WebSocket</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
    <link href="/main.css" rel="stylesheet">
    <script src="/webjars/jquery/jquery.min.js"></script>
    <script src="/webjars/sockjs-client/sockjs.min.js"></script>
    <script src="/webjars/stomp-websocket/stomp.min.js"></script>
    <script src="/app.js"></script>
</head>
<body>
<noscript><h2 style="color: #ff0000">Seems your browser doesn't support Javascript! Websocket relies on Javascript being
    enabled. Please enable
    Javascript and reload this page!</h2></noscript>
<div id="main-content" class="container">
    <div class="row">
        <div class="col-md-6">
            <form class="form-inline">
                <div class="form-group">
                    <label for="connect">WebSocket connection:</label>
                    <button id="connect" class="btn btn-default" type="submit">Connect</button>
                    <button id="disconnect" class="btn btn-default" type="submit" disabled="disabled">Disconnect
                    </button>
                </div>
            </form>
        </div>
        <div class="col-md-6">
            <form class="form-inline" id="send-form">
                <div class="form-group">
                    <label for="name">What is your name?</label>
                    <input type="text" id="name" class="form-control" placeholder="Your name here...">
                </div>
                <div class="form-group">
                    <label for="message">Message:</label>
                    <input type="text" id="message" class="form-control" placeholder="Your message here...">
                </div>
                <button id="send" class="btn btn-default" type="submit">Send</button>
            </form>
        </div>
    </div>
    <div class="row">
        <div class="col-md-12">
            <table id="conversation" class="table table-striped">
                <thead>
                <tr>
                    <th>Greetings</th>
                </tr>
                </thead>
                <tbody id="greetings">
                </tbody>
            </table>
        </div>
    </div>
</div>
</body>
</html>

 

app.js

var stompClient = null;

function setConnected(connected) {
    $("#connect").prop("disabled", connected);
    $("#disconnect").prop("disabled", !connected);
    if (connected) {
        $("#conversation").show();
    }
    else {
        $("#conversation").hide();
    }
    $("#greetings").html("");
}

function connect() {
    var socket = new SockJS('/app/gs-guide-websocket');
    stompClient = Stomp.over(socket);
    stompClient.connect({}, function (frame) {
        setConnected(true);
        console.log('Connected: ' + frame);
        stompClient.subscribe('/topic/greetings', function (greeting) {
            showGreeting(JSON.parse(greeting.body).content);
        });
    });
}

function disconnect() {
    if (stompClient !== null) {
        stompClient.disconnect();
    }
    setConnected(false);
    console.log("Disconnected");
}

function sendMessage() {
        const name = $("#name").val();
        const message = $("#message").val();
        stompClient.send("/app/hello", {}, JSON.stringify({'name': name, 'message': message}));
    }

function showGreeting(message) {
    $("#greetings").append("<tr><td>" + message + "</td></tr>");
}

$(function () {
    $("form").on('submit', function (e) {
        e.preventDefault();
    });
    $( "#connect" ).click(function() { connect(); });
    $( "#disconnect" ).click(function() { disconnect(); });
    $("#send").click(function() { sendMessage(); });
});

 

모든 구성을 확인했다면 다음으로 서버를 띄워서 확인해 보자.

 

 

 

각 다른 탭으로 Connection을 누르고 이름과 메시지를 기입하고 Send를 누르면 Greetings에 나타나게 된다.

이로써 STOMP를 활용해 WebSocketConfig이 구성에서 같은 broker의 /topic을 사용해서 발행하고 /app으로 구독해 STOMP 웹 소켓의 연결 엔드포인트를 설정해 사용했다.

 

자바 클래스 코드는 어렵지 않으나 스크립트는 필자가 공부해 본 적이 없기 때문에 보기에는 이해가 되나 코드를 짜거나 깊은 이해는 할 수 없었다.

다음 포스팅부터는 JavaScript와 JQuery를 배워보도록 하겠다.

'server' 카테고리의 다른 글

WebSocket Programming 채팅 예제  (0) 2024.06.28
Socket Programming 예제  (0) 2024.06.28
Socket과 WebSocket  (0) 2024.06.28
Nginx 사용해보기  (0) 2024.06.23
Nginx에 대해서  (0) 2024.06.22