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
<%@ 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 + ์ด๋ฒคํธ' ์ผ๋ก ์๋ช ํ๋ค.
'Spring' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Spring] WebSocket์ผ๋ก ์ค์๊ฐ ์ฑํ ๊ตฌํํ๊ธฐ (0) | 2023.12.05 |
---|---|
[Spring] MyBatis ์ Spring ์ฐ๋ํ๊ธฐ(3) : Interface Mapper๋ฅผ ์ฌ์ฉํ ์ฐ๋ (0) | 2023.12.01 |
[Spring] REST API Sever ๊ตฌ์ถ (0) | 2023.11.30 |
[Spring] JUnit๋ฅผ ์ด์ฉํ ๋จ์ํ ์คํธ(JDBC, HikariCP, MyBatis) (0) | 2023.11.30 |
[Spring] Spring AOP : @Aspect ์ฌ์ฉํ๊ธฐ (0) | 2023.11.29 |