티스토리 뷰

728x90
반응형

이번 포스팅에서는 스프링 부트 애플리케이션에서 웹 소켓을 활용하여 메시지를 송수신하는 방법에 대해 알아보겠습니다. 참고로, 아래 내용은 스프링 공식 사이트에서 제공하는 포스팅을 참고하여 작성한 글입니다.

Spring WebSocket 프로젝트 다운로드

https://start.spring.io/ 에 접속하여 WebSocket을 디펜던시로 추가한 후 스프링 부트 프로젝트를 다운로드합니다.

Spring Websocket 프로젝트 다운로드

다운로드한 프로젝트를 IntelliJ로 오픈한 후, Build.gradle파일을 열면 Websocket을 사용하는데 필요한 항목이 추가된 것을 보실 수 있습니다.

implementation 'org.springframework.boot:spring-boot-starter-websocket'

WebSocket과 TCP 네트워크

WebSocket은 웹에서 사용 가능한 Socket을 의미합니다. 네트워크에서 전송계층에 빠지지 않고 등장하는 것이 TCP인데요. Socket은 TCP 방식으로 네트워크를 연결합니다. TCP는 연결 지향형 프로토콜이므로, 세션을 생성한 이후로 서버와 클라이언트가 연결의 유지하며 통신이 가능합니다. 연결은 3-ways handshake, 연결 해제는 4-ways handshake 방식을 사용합니다. TCP 네트워크에 관하여 좀 더 자세히 알고 싶으면 아래 링크 확인 부탁드립니다. 

OSI 7 네트워크 계층 이해하기(TCP/UDP)

인터넷은 우리의 삶을 아주 편리하게 만들어 주는 통신기술입니다. 우리는 컴퓨터에서 브라우저라는 어플리케이션을 통해 데이터를 손쉽게 전송하고, 수신받을 수 있습니다.. 우리가 전송한 데

shcheon.tistory.com

웹 소켓을 사용한다는 것은 TCP 네트워크를 사용한다는 의미와 동일합니다. 사용하는 용어가 다를 뿐이라고 생각합니다.

웹 소켓을 통한 서버-클라이언트 간 메시지 교환하기

웹 소켓으로 서버와 클라이언트를 연결하여 서로 메시지를 주고받는 애플리케이션을 작성해보겠습니다. 개발하는 환경에서, JQuery, Bootstrap, STOMP, SockJS, webjar 라이브러리 사용이 필요하여 build.gradle 파일에 디펜던시 항목을 추가합니다.

implementation 'org.webjars:webjars-locator-core'
implementation 'org.webjars:sockjs-client:1.0.2'
implementation 'org.webjars:stomp-websocket:2.3.3'
implementation 'org.webjars:bootstrap:3.3.7'
implementation 'org.webjars:jquery:3.1.1-1'

다음으로, 클라이언트로부터 메시지를 수신받아 서버에서 처리하기 위해 Greeting, HelloMessage, GreetingController 클래스를 작성합니다.

package com.example.demo;

public class Greeting {

    private String content;

    public Greeting() {
    }

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

    public String getContent() {
        return content;
    }

}
package com.example.demo;

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 {
        return new Greeting("Hello, " + HtmlUtils.htmlEscape(message.getName()) + "!");
    }

}
package com.example.demo;

public class HelloMessage {

    private String name;

    public HelloMessage() {
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

다음으로 WebSocket 사용 설정에 관한 Config 클래스를 작성합니다.

package com.example.demo;

import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
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("/gs-guide-websocket").withSockJS();
    }

}

웹 소켓 설정 클래스에서 Broker, Destination 명칭, 엔드포인트를 지정하여 클라이언트와 메시지를 주고받을 접점을 지정합니다. 다음으로, 브라우저에게 보내줄 클라이언트 소스코드를 작성해보겠습니다.

<!DOCTYPE html>
<html>
<head>
    <title>Hello WebSocket</title>
    <link href="/webjars/bootstrap/css/bootstrap.min.css" rel="stylesheet">
    <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">
                <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>
                <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>
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('/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 sendName() {
    stompClient.send("/app/hello", {}, JSON.stringify({'name': $("#name").val()}));
}

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() { sendName(); });
});

상기 소스코드를 src/main/resource/static 경로에 index.html과 app.js 파일을 생성하여 코드를 저장합니다. 작성한 코드를 실행하면, 아래와 같이 브라우저 화면이 출력됩니다. 

웹서켓 서버 클라이언트 예제 화면
웹소켓 연결 중 서버 클라이언트 간 메세지 교환을 성공한 화면

웹 소켓으로 서버와 클라이언트가 연결되면, 메시지를 실시간으로 송수신이 가능해집니다. 웹소켓을 활용하면 웹에서 채팅 웹 애플리케이션 구현이 가능합니다.

728x90
반응형
댓글
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/09   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
글 보관함