๐Ÿฆ๋ฉ‹์Ÿ์ด ์‚ฌ์ž์ฒ˜๋Ÿผ 11๊ธฐ/์Šˆ๋ฉ‹์‚ฌ ํ”Œ์  - UniLearn ๐Ÿ’ก

[Spring][WebSocket] ์Šคํ”„๋ง STOMP ์‚ฌ์šฉํ•ด์„œ ์ฑ„ํŒ… ๊ตฌํ˜„ํ•˜๊ธฐ

1son 2023. 11. 3. 23:09

 

๋ฉ‹์Ÿ์ด ์‚ฌ์ž์ฒ˜๋Ÿผ - SWU์—์„œ ์ง„ํ–‰ํ•˜๋Š” ํ”„๋กœ์ ํŠธ์ธ 'UniLearn(์œ ๋‹ˆ๋Ÿฐ)'์ด ๊ฐœ๋ฐœ ์ฐฉ์ˆ˜ํ•ฉ๋‹ˆ๋‹ค. 

11์›” 6์ผ์— ๋น„๋Œ€๋ฉด์œผ๋กœ ํ”„๋กœ์ ํŠธ ๋ณด๊ณ ํšŒํ•˜๊ธฐ ์ „๊นŒ์ง€ 

 

ํœดํ•™์ƒ ํŒ€์› ํ•œ ๋ถ„์ด

jwt ๋กœ ์ธ์ฆ,์ธ๊ฐ€๊ตฌํ˜„์„ ํ†ตํ•ด ํšŒ์›๊ฐ€์ž…๊ณผ ๋กœ๊ทธ์ธ ๋กœ์ง์„ ์งœ์ฃผ์…”์„œ 

์ถ”๊ฐ€์ ์œผ๋กœ ์ฑ„ํŒ…์„ ๊ตฌํ˜„ํ•  ์ˆ˜์žˆ์„ ์ง€๋งŒ ๊ณต๋ถ€ํ•ด์˜ค๊ธฐ๋กœ ํ–ˆ์Šต๋‹ˆ๋‹ค. 

 

 

๋‚จ์€ ๊ฐœ๋ฐœ์€ ๊ฐ„์ง€ํ†ค์ด ๋๋‚˜๊ณ  ์ง„ํ–‰ํ•˜๊ธฐ๋กœ ํ–ˆ์Šต๋‹ˆ๋‹ค. 

 

๊ฐ„์ง€ํ†ค.. ๊บ„

 

 

 

์ฑ„ํŒ…์— ์•ž์„œ ์•„๋ฌด๊ฒƒ๋„ ๋ชจ๋ฅด๋Š” ์ €๋Š” ์˜์ƒ ๋‘๊ฐœ์™€

๋ธ”๋กœ๊ทธ ํ•˜๋‚˜๋ฅผ ์ฐธ๊ณ  ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ถ”๊ฐ€์ ์œผ๋กœ spring ์‚ฌ์ดํŠธ๋„ ์ฐธ๊ณ ํ–ˆ๋„ค์š”

 

https://www.youtube.com/watch?v=8iwNDEXldAk

https://www.youtube.com/watch?v=rvss-_t6gzg

๋ธ”๋กœ๊ทธ : 

https://growth-coder.tistory.com/157

https://spring.io/guides/gs/messaging-stomp-websocket/

 

 

 

 


 

 

 

์›น ์†Œ์ผ“์€ html5๊ฐ€ ๋‚˜์˜ค๋ฉด์„œ ์†Œ๊ฐœ๋˜์—ˆ์œผ๋ฉฐ 

Ajax ํ†ต์‹ ์œผ๋กœ ํ•  ์ˆ˜๋„ ์žˆ๋Š”๋ฐ ์†Œ์ผ“ํ†ต์‹ ์œผ๋กœ ํ•˜๋ฉด ์ข‹์€ ์ ์€, 

์—ฐ๊ฒฐ ์ค‘์— ์™”๋‹ค๊ฐ”๋‹ค ํ•˜๋Š” ๋ฐ์ดํ„ฐ์— ํ—ค๋”๊ฐ€ ํฌํ•จ์ด ์•ˆ๋˜๊ธฐ ๋•Œ๋ฌธ์— ์šฉ๋Ÿ‰์ด ์ž‘๋‹ค๋Š” ์ด์ ์ด ์žˆ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. 

 

์Šคํ”„๋ง - ๊ฐ€์ด๋“œ - websocket์„ ์ฐธ๊ณ ํ•˜๋ฉด 

https://spring.io/guides/gs/messaging-stomp-websocket/

 

Getting Started | Using WebSocket to build an interactive web application

In Spring’s approach to working with STOMP messaging, STOMP messages can be routed to @Controller classes. For example, the GreetingController (from src/main/java/com/example/messagingstompwebsocket/GreetingController.java) is mapped to handle messages t

spring.io

์—ฌ๊ธฐ์„œ ํŠน์ง•์ ์œผ๋กœ ๋‚˜์˜ค๋Š” ๋‹จ์–ด๊ฐ€ ์žˆ๋Š”๋ฐ, 

STOMP ์ž…๋‹ˆ๋‹ค. 

์šฐ๋ฆฌ๋Š” stomp๋ผ๋Š” ์Šคํƒ์„ ์‚ฌ์šฉํ•ด์„œ ๊ตฌํ˜„ํ•ด๋ณผ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทผ๋ฐ ๊ตณ์ด stomp ์‚ฌ์šฉํ•˜์ง€ ์•Š์•„๋„ ์›น์†Œ์ผ“์€ ์‚ฌ์šฉ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค

STOMP : Simple (or Streaming) Text Orientated Messaging Protocol.

ํ”„๋กœํ† ์ฝœ์ด๋‹ˆ, ๊ทœ์•ฝ์ด๋ผ๊ณ  ์ƒ๊ฐํ•˜์‹œ๋ฉด ๋  ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. 

 

์Šคํ”„๋ง์—์„œ๋Š” STOMP๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์›น ์†Œ์ผ“์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. 

๊ฐ„๋‹จํ•œ ๋ฉ”์‹œ์ง€๋ฅผ ์ „์†กํ•˜๊ธฐ ์œ„ํ•œ ํ”„๋กœํ† ์ฝœ๋กœ ๋ฉ”์‹œ์ง€ ๋ธŒ๋กœ์ปค๋ฅผ์™€ publisher - subscriber ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•˜๋Š”๋ฐ์š”.

๋ฉ”์‹œ์ง€์˜ ๋ฐœํ–‰์ž์™€ ๊ตฌ๋…์ž๊ฐ€ ์กด์žฌํ•˜๊ณ  ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋‚ด๋Š” ์‚ฌ๋žŒ๊ณผ ๋ฐ›๋Š” ์‚ฌ๋žŒ์ด ๊ตฌ๋ถ„๋˜์–ด ์žˆ์œผ๋ฉฐ

๋ฉ”์‹œ์ง€ ๋ธŒ๋กœ์ปค๋Š” ๋ฐœํ–‰์ž๊ฐ€ ๋ณด๋‚ธ ๋ฉ”์‹œ์ง€๋ฅผ ๊ตฌ๋…์ž์—๊ฒŒ ์ „๋‹ฌํ•ด์ฃผ๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.

STOMP๋Š” HTTP์™€ ๋น„์Šทํ•˜๊ฒŒ frame ๊ธฐ๋ฐ˜ ํ”„๋กœํ† ์ฝœ command, header, body๋กœ ์ด๋ฃจ์–ด์ ธ ์žˆ์–ด์š” 

๊ฐœ๋ฐœ์ž ๋„๊ตฌ๋กœ ์ง์ ‘ ํ™•์ธ๋„ ๊ฐ€๋Šฅํ•ด์š” 

 

<STOMP frame ๊ตฌ์กฐ>

COMMAND
header1:value1
header2:value2
Body^@

 

 


 

์Šคํ”„๋ง ์›น ์†Œ์ผ“ ๊ตฌํ˜„

https://spring.io/guides/gs/messaging-stomp-websocket/

์Šคํ”„๋ง - ๊ฐ€์ด๋“œ - websocket

 

Getting Started | Using WebSocket to build an interactive web application

In Spring’s approach to working with STOMP messaging, STOMP messages can be routed to @Controller classes. For example, the GreetingController (from src/main/java/com/example/messagingstompwebsocket/GreetingController.java) is mapped to handle messages t

spring.io

์—ฌ๊ธฐ ๋‹ค ๋‚˜์™€ ์žˆ์Šต๋‹ˆ๋‹ค. ๋Œ€๋žต์ ์ธ๊ฑด..

 

 

start.spring.io์—์„œ websocket dependency๋ฅผ ์ถ”๊ฐ€ํ•ด์คฌ์Šต๋‹ˆ๋‹ค. 

Spring Boot : 2.7.17

Packaging : Jar

Java : 11

 

ํ”„๋กœ์ ํŠธ๊ฐ€ ๋งŒ๋“ค์–ด์ง€๋ฉด 

์—ฌ๋Ÿฌ ํŒŒ์ผ์„ ์ƒ์„ฑํ•ด์ค˜์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

<build.gradle>

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-websocket'
	implementation 'org.webjars:webjars-locator-core'
	implementation 'org.webjars:sockjs-client:1.5.1'
	implementation 'org.webjars:stomp-websocket:2.3.4'
	implementation 'org.webjars:bootstrap:5.2.3'
	implementation 'org.webjars:jquery:3.6.4'
	implementation 'org.projectlombok:lombok:1.18.26'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'

}

 

 

์ƒˆ๋กœ ๋งŒ๋“  <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">
                <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>

 

 

 

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

 

<HelloMessage.java>

package webSocketTest.webSocket;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Getter
@Setter
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;}
}

 

<Greeting.java>

package webSocketTest.webSocket;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
public class Greeting {
    private String content;

    public Greeting(){

    }

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

    public String getContent(){return content;}
}

 

 

<GreetingController>

package webSocketTest.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("Hello, " + HtmlUtils.htmlEscape(message.getName()) + "!");
    }

}

 

 

<WebSocketConfig>

package webSocketTest.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
@Controller
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();
    }

}

 

 

<WebSocketApplication> ์ด๊ฑฐ๋Š” ๊ธฐ๋ณธ์œผ๋กœ ์žˆ๋Š”๊ฑฐ๊ณ  .. 

 

 

 

 

์ข‹๋‹ค. ์ด์ œ  WebSocketApplication ์— ๋“ค์–ด๊ฐ€์„œ ์‹คํ–‰๋ฒ„ํŠผ ๋ˆ„๋ฅด๊ณ  

๊ฒ€์ƒ‰์ฐฝ์— localhost:8080์„ ๊ฒ€์ƒ‰ํ•œ๋‹ค.

 

---

์—ฌ๊ธฐ์„œ ๋ถ€ํ„ฐ ์ขŒ์ถฉ์šฐ๋Œ ์—๋Ÿฌ ๋ฐœ์ƒ๊ธฐ ....

 

๋‚˜๋Š” ๊ทธ๋ƒฅ ํ•˜๋ผ๋Š” ๋Œ€๋กœ ํ•œ๊ฑด๋ฐ ์™œ ์—๋Ÿฌ๊ฐ€.. ... .. 

 

 

connet๊ฐ€ ์•ˆ๋œ๋‹ค. ์™œ.. ?

f12๋ฅผ ๋ˆŒ๋Ÿฌ ๊ฐœ๋ฐœ์ž ๋ชจ๋“œ์— ๋“ค์–ด๊ฐ€์„œ ์—๋Ÿฌ๋ฅผ ํ™•์ธํ–ˆ๋‹ค. connet๊ฐ€ ์•ˆ๋ˆŒ๋ ธ๊ฑฐ๋“ .. 

 

 

1. Failed to load resource: the server responded with a status of 404 () stomp.min.js:8 Whoops! Lost connection to http://localhost:8080/gs-guide-websocket stomp.min.js:8 Opening Web Socket... :8080/gs-guide-websocket/info?t=1699014111573:1

 

 

์›น ์†Œ์ผ“์„ ์—ด ๋•Œ gs-guide-websocket์„ ๋ชป์ฐพ๊ฒ ๋‹ค ๋Š” ๋œป ์ธ๊ฑฐ ๊ฐ™๋‹ค. ๋Œ€์ถฉ?

 

 

https://stackoverflow.com/questions/67421263/can%C2%B4t-establish-connection-to-websocket-whoops-lost-connection-to-http-local

 

Can´t establish connection to websocket "Whoops! Lost connection to http://localhost:8080"

I´m trying to implement a websocket in my spring boot application, but I´m unable to create a connection. I used this video and its corresponding git-repo to create the following config for the ser...

stackoverflow.com

์Šคํƒ ์˜ค๋ฒ„ํ”Œ๋กœ์šฐ ์งฑ 

 

app.js์—์„œ connect() ํ•จ์ˆ˜์˜ socket path ์•ž์— /app/์„ ๋ง๋ถ™์—ฌ ์ฃผ์—ˆ๋‹ค. 

 

 

 

 

 

 


 

์ด์ œ ๋‹ค๋ฅธ ์—๋Ÿฌ๊ฐ€ ๋‚˜์™”๋‹ค. 

2. Uncaught ReferenceError: SockJS is not defined ์—๋Ÿฌ 

 

https://jindevelopetravel0919.tistory.com/96

 

[์—๋Ÿฌ] Uncaught ReferenceError: SockJS is not defined

[Reason] WebSocket ์„ ์—ฐ๊ฒฐํ•˜๊ณ  ๊ฐ„๋‹จํ•˜๊ฒŒ ์ •์ƒ์ ์œผ๋กœ ๋™์ž‘์ด ์ˆ˜ํ–‰๋˜๋Š”์ง€ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด ๊ฐ„๋‹จํ•œ ์œ ์‚ฌ 1์ธ ์ฑ„ํŒ… ํŽ˜์ด์ง€๋ฅผ ๋งŒ๋“ค๊ณ  ์‹คํ–‰ํ–ˆ์œผ๋‚˜ "Uncaught ReferenceError: SockJS is not defined" ํ•ด๋‹น ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜

jindevelopetravel0919.tistory.com

index.html ์˜ header ๋ถ€๋ถ„์— sockjs์— ๊ด€๋ จํ•œ ์ฝ”๋“œ๋ฅผ ๋„ฃ์–ด์ฃผ์—ˆ๋‹ค. 

 

 

 


 

 

 

3. Uncaught ReferenceError: Stomp is not defined ์—๋Ÿฌ 

์ข‹์•„ . ์•„์˜ˆ script ๋‹ค์‹œ ๊ฐˆ์•„๋ผ์› ๋‹ค.

 

 

์ด์ œ ์Šฌ์Šฌ ๋•Œ๋ ค์น˜๊ณ  ์‹ถ์—ˆ๋‹ค..

4. 

๊ทผ๋ฐ ์ด๊ฑฐ ๊ตฌ๊ธ€๋ง ํ•ด๋„ ์•ˆ๋‚˜์˜ค๊ธธ๋ž˜ ,, 

์ฒซ๋ฒˆ์งธ ์—๋Ÿฌ๋ž‘ ๋น„์Šทํ•ด์„œ ๋•Œ๋ ค๋งž์ท„๋”๋‹ˆ ๋๋‹ค. 

addEndpoint path์— /app/์„ ์ถ”๊ฐ€ ํ•ด์ฃผ์—ˆ๋‹ค. 

 

 

 

----


๊ฒฐ๊ตญ ๋๋‹ค. ์›น์†Œ์ผ“ ์„ฑ๊ณต

 

 

ํƒญ์„ ํ•˜๋‚˜ ๋” ์—ด์–ด์„œ ์ ‘์†ํ•ด๋ณด๋ฉด ๋‹ค๋ฅธ ํƒญ์—์„œ ๋ณด๋‚ธ ์ด๋ฆ„์ด ๋ณด์ด๋Š” ๊ฒƒ๋„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

 

 

 

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์Šคํ”„๋ง์œผ๋กœ ์‹ค์‹œ๊ฐ„ ์ฑ„ํŒ… ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ๋„ ๋ฌธ์ œ ์—†๋‹ค! 

์•„๋‹ˆ ๊ทธ๊ฑด ๋‹ค๋ฅด๋ ค๋‚˜..

 

๊ณต๋ถ€ํ•˜๋ฉด์„œ ๋А๋‚€ ์ ์€ .. 

์˜์–ด ๊ณต๋ถ€ํ•ด์•ผ๊ฒ ๋‹ค. ... 

์Šคํƒ์˜ค๋ฒ„ํ”Œ๋กœ์šฐ ์งฑ..  

 

 

 

๐Ÿ”—๊นƒํ—ˆ๋ธŒ ๋งํฌ 

https://github.com/hansun-hub/webSocket

 

GitHub - hansun-hub/webSocket: 11-03 ์Šˆ๋ฉ‹์‚ฌ ํ”„๋กœ์ ํŠธ๋ฅผ ์œ„ํ•œ ์Šคํ”„๋ง ์†Œ์ผ“ํ”„๋กœ๊ทธ๋ž˜๋ฐ์ž…๋‹ˆ๋‹ค. STOMP ์‚ฌ์šฉ

11-03 ์Šˆ๋ฉ‹์‚ฌ ํ”„๋กœ์ ํŠธ๋ฅผ ์œ„ํ•œ ์Šคํ”„๋ง ์†Œ์ผ“ํ”„๋กœ๊ทธ๋ž˜๋ฐ์ž…๋‹ˆ๋‹ค. STOMP ์‚ฌ์šฉ. Contribute to hansun-hub/webSocket development by creating an account on GitHub.

github.com