Spring

[Spring] WebSocket ๊ธฐ์ดˆ ์˜ˆ์ œ

developer of the night sky 2023. 12. 1. 22:01

Socket? WebSocket?๐Ÿ”Ž

 

- Socket

  • Socket๋Š” ๋„คํŠธ์›Œํฌ ํ†ต์‹ ์„ ์œ„ํ•œ ๋„๊ตฌ๋กœ, ๋ฌด์ „๊ธฐ๋‚˜ ์ „ํ™”๊ธฐ์™€ ๊ฐ™์ด ํ”„๋กœ๊ทธ๋žจ ๊ฐ„์— ๋ฐ์ดํ„ฐ๋ฅผ ์ฃผ๊ณ ๋ฐ›์„ ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค€๋‹ค. ์ด๋Š” ํŠน์ •ํ•œ ์ธ์Šคํ„ด์Šค๊ฐ€ ์•„๋‹Œ ํ†ต์‹  ๊ทœ๊ฒฉ์„ ๋‚˜ํƒ€๋‚ธ๋‹ค.
  • ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด๋“ค์€ ์ด๋ฏธ Socket์„ ๊ตฌํ˜„ํ•ด๋‘์–ด ํ”„๋กœ๊ทธ๋ž˜๋จธ๊ฐ€ ์†์‰ฝ๊ฒŒ ๋„คํŠธ์›Œํฌ ํ†ต์‹ ์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ๋ธŒ๋ผ์šฐ์ €๋„ ๋„คํŠธ์›Œํฌ๋ฅผ ํ†ตํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ์ฃผ๊ณ ๋ฐ›์„ ๋•Œ Socket๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ†ต์‹ ํ•œ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ตœ๊ทผ์—๋Š” ์›น ๊ธฐ์ˆ ์˜ ๋ฐœ์ „์œผ๋กœ ์ธํ•ด Socket ์‚ฌ์šฉ๋ฅ ์ด ์ค„์–ด๋“ค์—ˆ๋‹ค.

- WebSocket

  • WebSocket์€ ์›น์ƒ์—์„œ ๋™์ž‘ํ•˜๋Š” Socket์œผ๋กœ, ๊ธฐ์กด์˜ ์›น ํ†ต์‹  ๋ฐฉ์‹๊ณผ๋Š” ๋‹ค๋ฅด๊ฒŒ ์–‘๋ฐฉํ–ฅ ํ†ต์‹ ์„ ์ง€์›ํ•œ๋‹ค.
  • Ajax์™€ ์œ ์‚ฌํ•œ ๋ฉด์ด ์žˆ์ง€๋งŒ Ajax๋Š” ๋‹จ๋ฐฉํ–ฅ ํ†ต์‹ ์— ์ฃผ๋กœ ์‚ฌ์šฉ๋˜๋ฉฐ, WebSocket์€ ์›น ํŽ˜์ด์ง€์—์„œ ์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›๋Š” ๊ฒƒ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ, ์›น ํŽ˜์ด์ง€์—์„œ ์„œ๋ฒ„๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๋‚ด๋Š” ์–‘๋ฐฉํ–ฅ ํ†ต์‹ ์ด ๊ฐ€๋Šฅํ•˜๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ๋‹ค์–‘ํ•œ ์‹ค์‹œ๊ฐ„ ๋ฐ์ดํ„ฐ๋ฅผ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ์ ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
  • WebSocket์€ ๊ธฐ์กด์˜ ์›น ํ†ต์‹  ๋ฐฉ์‹๋ณด๋‹ค ๋น ๋ฅด๊ณ  ํšจ์œจ์ ์ด๋ฉฐ, ์‹ค์‹œ๊ฐ„ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๊ธฐ ์œ„ํ•ด ๋„๋ฆฌ ์‚ฌ์šฉ๋˜๊ณ  ์žˆ๋‹ค.

WebSocket ํ”„๋กœ์ ํŠธ๐Ÿ”Ž

WebSocket๋ฅผ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋Š” ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ํ•œ๋‹ค.

 

- ํŒŒ์ผ ๊ตฌ์„ฑ

์ƒ์œ„ ํŒจํ‚ค์ง€(ํด๋”) ํ•˜์œ„ ํŒจํ‚ค์ง€(ํด๋”) ํŒŒ์ผ๋ช…
src/main/java com.test.controller SocketController.java
  com.test.server SocketServer.java
WEB-INF views test.jsp

 


- ํ™˜๊ฒฝ ์„ค์ •

1. ์ž๋ฐ” ๋ฐ ์Šคํ”„๋ง ๋ฒ„์ „ ๋ณ€๊ฒฝ - pom.xml 

2. ์˜์กด์„ฑ ์ถ”๊ฐ€

 

WebSocket๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ ์˜์กด์„ฑ์„ ์ถ”๊ฐ€ํ•œ๋‹ค.

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-websocket</artifactId>
			<version>${org.springframework-version}</version>
		</dependency>
	
		<dependency>
			<groupId>javax.websocket</groupId>
			<artifactId>javax.websocket-api</artifactId>
			<version>1.1</version>
		</dependency>

 


- SocketServer.java

WebSoket ์œผ๋กœ ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„๊ฐ€ ํ†ต์‹ ํ•  ๋•Œ๋Š” Controller์˜ ์—ญํ• ์€ view๋ฅผ ๋„์–ด์ฃผ๋Š” ์—ญํ• ๋งŒ ์กด์žฌํ•œ๋‹ค. 

package com.test.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class SocketController {
	
	@GetMapping(value = "/test.do")
	public String test(Model model) {
		return "test";
	}
}

 


๐Ÿ“ข ์ž ๊น ์—ฌ๊ธฐ์„œ, ํด๋ผ์ด์–ธํŠธ์™€ SocketServer ์˜ ๊ด€๊ณ„

1. ์ผ๋ฐฉ์ ์ธ ๋ฐ์ดํ„ฐ ์†ก์ˆ˜์‹ 

์›น ์†Œ์ผ“์„ ์‚ฌ์šฉํ•˜๋ฉด ์–‘๋ฐฉํ–ฅ ํ†ต์‹ ์ด ๊ฐ€๋Šฅํ•˜๋ฉฐ, ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„ ๊ฐ„์— ์–ธ์ œ๋“  ๋ฐ์ดํ„ฐ๋ฅผ ์ฃผ๊ณ  ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค. ์ด๋Š” HTTP์™€๋Š” ๋‹ค๋ฅด๊ฒŒ ์ผ๋ฐฉ์ ์ธ ํด๋ผ์ด์–ธํŠธ์—์„œ ์š”์ฒญํ•˜๊ณ  ์„œ๋ฒ„๊ฐ€ ์‘๋‹ตํ•˜๋Š” ๊ตฌ์กฐ๊ฐ€ ์•„๋‹Œ, ์–‘์ชฝ์—์„œ ์–ธ์ œ๋“  ๋ฐ์ดํ„ฐ๋ฅผ ์ฃผ๊ณ  ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค.

 

2. ํด๋ผ์ด์–ธํŠธ์˜ ์—ฐ๊ฒฐ ์‹œ์ž‘

Socketserver๋Š” ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋ˆ„๊ตฐ์ง€ ๋ชจ๋ฅด๊ธฐ ๋•Œ๋ฌธ์—  ์›น ์†Œ์ผ“์—์„œ๋Š” ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋จผ์ € ์—ฐ๊ฒฐ์„ ์‹œ์ž‘ํ•ด์•ผ ํ•œ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ํด๋ผ์ด์–ธํŠธ๋Š” ์„œ๋ฒ„์—๊ฒŒ ์—ฐ๊ฒฐ์„ ์š”์ฒญํ•˜๊ณ , ์„œ๋ฒ„๋Š” ํ•ด๋‹น ์—ฐ๊ฒฐ์„ ์ˆ˜๋ฝํ•˜์—ฌ ์–‘๋ฐฉํ–ฅ ํ†ต์‹ ์ด ๊ฐ€๋Šฅํ•œ ์ƒํƒœ๊ฐ€ ๋œ๋‹ค.


3. @ServerEndpoint

@ServerEndpoint ์–ด๋…ธํ…Œ์ด์…˜์€ Java์—์„œ ์›น ์†Œ์ผ“ ์—”๋“œํฌ์ธํŠธ๋ฅผ ์ •์˜ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋œ๋‹ค. ์ข…๋‹จ์ ์€ ์›น ์†Œ์ผ“ ์„œ๋ฒ„์—์„œ ํด๋ผ์ด์–ธํŠธ์˜ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๊ณ , ์—ฐ๊ฒฐ์„ ๊ด€๋ฆฌํ•˜๋Š” ํ•ต์‹ฌ ๊ตฌ์„ฑ ์š”์†Œ์ด๋‹ค.

 

4. ์—ฐ๊ฒฐ ์ง€์†์„ฑ

ํ•œ ์ชฝ์—์„œ ์ผ๋ฐฉ์ ์œผ๋กœ ์—ฐ๊ฒฐ์„ ๋Š์–ด๋ฒ„๋ฆฌ์ง€ ์•Š๋Š” ํ•œ, ์›น ์†Œ์ผ“ ์—ฐ๊ฒฐ์€ ๊ณ„์†ํ•ด์„œ ์ง€์†๋œ๋‹ค. ์ด ํŠน์ง•์€ HTTP์™€ ๋‹ฌ๋ฆฌ ์ง€์†์ ์ธ ์–‘๋ฐฉํ–ฅ ํ†ต์‹ ์ด ๊ฐ€๋Šฅํ•˜๋„๋ก ํ•œ๋‹ค.


- WebSocket ์—ฐ๊ฒฐํ•˜๊ธฐ

์œ„ 2๋ฒˆ ํŠน์ง•์œผ๋กœ ํด๋ผ์ด์–ธํŠธ(jsp)์—์„œ ๋จผ์ € ์—ฐ๊ฒฐ ์‹œ๋„๋ฅผ ํ•œ๋‹ค.

ํ™”๋ฉด์˜ ์—ฐ๊ฒฐ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด 4๊ฐ€์ง€ ๋‹จ๊ณ„๊ฐ€ ์ด๋ค„์ ธ์•ผํ•œ๋‹ค.

1. ์†Œ์ผ“ ์ƒ์„ฑ

2. ์„œ๋ฒ„ ์ ‘์†(์—ฐ๊ฒฐ)

3. ํ†ต์‹ 

4. ์„œ๋ฒ„ ์ ‘์† ํ•ด์ œ(์ข…๋ฃŒ)

 

test.jsp

test.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>WebSocketTest</title>
<link rel="stylesheet" href="https://me2.do/5BvBFJ57">
</head>
<body>
	<!-- test.jsp -->
	<h1>WebSocket <small>์—ฐ๊ฒฐ ํ…Œ์ŠคํŠธ</small></h1>
	
	<div>
		<button type="button" class="in" id="btnConnect">์—ฐ๊ฒฐํ•˜๊ธฐ</button>
		<button type="button" class="out" id="btnDisConnect">์ข…๋ฃŒํ•˜๊ธฐ</button>
	</div>
	<hr>
	
	<div>
		<input type="text" class="long" id="msg">
		<button type="button" id="btnMsg">๋ณด๋‚ด๊ธฐ</button>
	</div>
	
	<div class="message full"></div>
	<script src="https://code.jquery.com/jquery-1.12.4.js" ></script>
</body>
</html>

 

 

test.jsp (JavaScript)

	<script>
		const url = 'ws://localhost:8090/socket/testserver.do';
		
		let ws; //์›น ์†Œ์ผ“ ์ฐธ์กฐ ๋ณ€์ˆ˜
        
		$('#btnConnect').click(function() {
			
			ws = new WebSocket(url);
			
			ws.onopen = function(evt) {
				log('์„œ๋ฒ„์™€ ์—ฐ๊ฒฐํ•˜์˜€์Šต๋‹ˆ๋‹ค.');
			};
			
			ws.onclose = function(evt) {
				log('์„œ๋ฒ„์™€ ์—ฐ๊ฒฐ์ด ์ข…๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.');
			};
			
			ws.onmessage = function(evt) {
				log(evt.data);
			};
			
			ws.onerror = function(evt) {
				log('์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.' + evt);
			};
		});
		
		$('#btnDisConnect').click(function() {
			ws.close();
			log('์„œ๋ฒ„์™€ ์—ฐ๊ฒฐ ์ข…๋ฃŒ๋ฅผ ์‹œ๋„ํ•ฉ๋‹ˆ๋‹ค.');
			
		});
		
		function log(msg) {
			$('.message').prepend(`
				<div>[\${new Date().toLocaleTimeString()}] \${msg}</div>		
			`);
		}
		
		$('#btnMsg').click(function() {
			ws.send($('#msg').val());
			log('๋ฉ”์‹œ์ง€๋ฅผ ์ „์†กํ–ˆ์Šต๋‹ˆ๋‹ค.');
			
			$('#msg').val('');
		});
		
	</script>

 

 

const url = 'ws://localhost:8090/socket/testserver.do';

ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„ ์—ฐ๊ฒฐ ํ•  ๋•Œ๋Š” 'http' ์ด ์•„๋‹Œ WebSocket ์˜ ์•ฝ์ž์ธ 'ws' ํ”„๋กœํ† ์ฝœ์„ ์‚ฌ์šฉํ•œ๋‹ค.

์œ„ ์ฃผ์†Œ ์ค‘ testserver.do๋Š” ์„œ๋ฒ„์˜ @ServerEndpoint ์™€ ์—ฐ๊ฒฐํ•˜์—ฌ ํด๋ผ์ด์–ธํŠธ์—์„œ ์„œ๋ฒ„๋ฅผ ๋งคํ•‘ํ•˜๋Š” ์—ญํ• ์„ ํ•œ๋‹ค. 

 

ws = new WebSocket(url);

WebSocket ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์†Œ์ผ“ ์ƒ์„ฑ๊ณผ ๋™์‹œ์— ์„œ๋ฒ„์— ์ ‘์† ์‹œ๋„ํ•œ๋‹ค.

 

์›น ์†Œ์ผ“ ์ด๋ฒคํŠธ

์›น ์†Œ์ผ“์—๋Š” ๊ฐ์ข… ํ–‰์œ„๋“ค์ด ์ด๋ฒคํŠธ๋กœ ๊ตฌํ˜„๋˜์–ด์žˆ์–ด, ํด๋ผ์ด์–ธํŠธ๋Š” ๋น„๋™๊ธฐ ๋ฐฉ์‹์œผ๋กœ ๋‹ค๋ฅธ ์—…๋ฌด๋ฅผ ํ•˜๋‹ค๊ฐ€ ์ด๋ฒคํŠธ๋กœ ์—ฐ๋ฝ ์˜ค๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

ws.onopen : ์„œ๋ฒ„์ธก์—์„œ ์†Œ์ผ“ ์—ฐ๊ฒฐ์„ ๋ฐ›์•„๋“ค์ด๊ณ  ์—ฐ๊ฒฐ์ด ๋˜๋Š” ์ˆœ๊ฐ„ ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

ws.onclose : ์›น ์†Œ์ผ“ ์—ฐ๊ฒฐ์ด ๋‹ซํž ๋•Œ ๋ฐœ์ƒํ•œ๋‹ค.

ws.onmessage : ์›น ์†Œ์ผ“์œผ๋กœ๋ถ€ํ„ฐ ๋ฉ”์‹œ์ง€๋ฅผ ์ˆ˜์‹ ํ–ˆ์„ ๋•Œ ๋ฐœ์ƒํ•œ๋‹ค.

ws.onerror : ์›น ์†Œ์ผ“ ํ†ต์‹  ์ค‘ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ ํ˜ธ์ถœ๋œ๋‹ค.

 

 

ws.send($('#msg').val());

์—ฐ๊ฒฐ๋œ ์„œ๋ฒ„์—๊ฒŒ ๋ฉ”์‹œ์ง€๋ฅผ ์ „์†กํ•  ๋•Œ๋Š” ws.send('์ „๋‹ฌํ•  ๋ฉ”์‹œ์ง€') ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

๋ฉ”์‹œ์ง€๋ฅผ ์„œ๋ฒ„์— ์ „์†กํ•˜๊ณ ๋‚˜๋ฉด ๋‹ค์Œ ์ž…๋ ฅ์„ ์œ„ํ•ด ์ดˆ๊ธฐํ™”๋ฅผ ํ•œ๋‹ค.

 

SocketServer.java

package com.test.server;

@ServerEndpoint("/testserver.do")
public class SocketServer {

	@OnOpen
	public void handelOpen() {
		System.out.println("ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ ‘์†ํ–ˆ์Šต๋‹ˆ๋‹ค.");
	}
	
	@OnClose
	public void handleClose() {
		System.out.println("ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ข…๋ฃŒํ–ˆ์Šต๋‹ˆ๋‹ค.");
	}
	
	@OnMessage
	public String handleMasseage(String msg) {
		System.out.println("ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋ณด๋‚ธ ๋ฉ”์‹œ์ง€: " + msg);
		
		return "(์‘๋‹ต)" + msg;
	}
	
	@OnError
	public void handleError(Throwable e) {
		System.out.println("์—๋Ÿฌ ๋ฐœ์ƒ " + e.getMessage());
	}
	
}

 

@ServerEndpoint("/testserver.do")

์œ„์—์„œ ํด๋ผ์ด์–ธํŠธ๊ฐ€ testserver.do ๋ฅผ ๋งคํ•‘ํ•˜์˜€๋‹ค.

 

@OnMessage

์„œ๋ฒ„ ์ธก์—์„œ ์›น ์†Œ์ผ“ ์ด๋ฒคํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ์–ด๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•œ๋‹ค.

์ด ์–ด๋…ธํ…Œ์ด์…˜์€ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์„œ๋ฒ„์—๊ฒŒ ๋ฉ”์‹œ์ง€๋ฅผ ์ „์†กํ–ˆ์„ ๋•Œ(ws.send) ๋ฐ˜์‘ํ•˜๋Š” ์ด๋ฒคํŠธ์ด๋‹ค.  ์ „๋‹ฌํ•œ ๋ฉ”์‹œ์ง€๊ฐ€ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์„ค์ •๋œ๋‹ค.

 

๋ณดํ†ต ๋ฉ”์†Œ๋“œ ์ด๋ฆ„์€ 'handle + ์ด๋ฒคํŠธ' ์œผ๋กœ ์ž‘๋ช…ํ•œ๋‹ค.

 

์—ฐ๊ฒฐ ๋ฐ ๋ฉ”์‹œ์ง€ ์ „์†ก ๋ชจ์Šต

 

์—ฐ๊ฒฐ, ์ „์†ก, ์—ฐ๊ฒฐ์ข…๋ฃŒ