2024. 10. 10. 17:13ㆍSpring
오늘은 웹소켓을 활용하여 메모장 기능을 한 번 구현해볼 것이다.
Ajax와 WebSocket의 차이
연결의 지속성에 따라 둘을 구분한다.
클라이언트와 서버가 통신할 때 HTTP통신을 주로 사용한다.
HTTP통신은 다음과 같은 특징이 있다.
1. 비연결성 (connectionless) : 연결을 맺고 요청을 하고 응답을 받으면 연결을 끊어버린다.
2. 무상태성 (stateless) : 서버가 클라이언트의 상태를 가지고 있지 않는다.
3. 단방향 통신이다.
이러한 HTTP 통신의 경우 채팅과 같은 실시간 통신에 적합하지 않다.
물론 HTTP 통신으로 실시간 통신을 흉내낼 수는 있으나 완벽하지는 않다.
실시간 통신이 필요할 때 사용하는 통신을 소켓 통신이라고 한다.
HTTP통신과 다르게 연결을 맺고 바로 끊어버리는게 아니라 계속 유지를 하기 때문에 실시간 통신에 적합하다.
Ajax
JavaScript를 이용해 서버와 브라우저가 비동기 방식으로 데이터를 교환할 수 있는 통신 기능
- 데이터를 주고 받는 형식.
- 요청과 응답이 존재한다.
- HTTP를 이용한 요청과 응답.
- 클라이언트의 요청이 없으면 서버의 응답도 없다.
WebSocket
사용자의 브라우저와 서버 사이의 인터액티브 통신 세션을 설정할 수 있게 하는 고급 기술
- 클라이언트의 요청이 없어도 서버의 응답이 존재할 수 있다.
- 웹소켓 연결을 끊어버리기 전까지는 자유롭게 요청, 응답이 오고 갈 수 있다.
home.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:set var="cpath" value="${pageContext.request.contextPath }" />
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="https://cdn.jsdelivr.net/sockjs/1/sockjs.min.js"></script>
<style>
#notepad {
box-sizing: border-box;
width: 700px;
height: 400px;
padding: 10px;
margin: 10px 0;
border: 2px solid black;
font-size: 17px;
overflow-y: auto;
}
form > p {
box-sizing: border-box;
width: 700px;
display: flex;
justify-content: space-between;
}
input[name="input"] {
padding: 5px;
font-size: 20px;
flex: 5;
margin-right: 5px;
}
input[type="submit"] {
flex: 1;
}
</style>
</head>
<body>
<h1>websocket 을 이용한 메모장 (sockJS)</h1>
<hr>
<div id="notepad">
</div>
<form>
<p><input type="text" name="input" placeholder="글을 입력">
<input type="submit">
</p>
</form>
<script>
// 변수선언
const cpath = '${cpath}'
const form = document.forms[0]
const ws = new SockJS(cpath + '/chat')
const notepad = document.getElementById('notepad')
// 함수정의
function messageHandler(event) {
notepad.innerHTML = '<p>' + event.data + '</p>'
notepad.scroll({
top : notepad.scrollHeight,
behavior : 'smooth',
})
}
function submitHandler(event) {
event.preventDefault()
const input = event.target.querySelector('input[name="input"]')
ws.send(input.value)
input.value = ''
input.focus()
}
// 이벤트 연결
ws.onmessage = messageHandler
ws.onopen = function(msg) {}
ws.onclose = function(msg) {}
ws.onerror = function(msg) {}
form.onsubmit = submitHandler
</script>
</body>
</html>
ChatComponent
import java.util.ArrayList;
import java.util.List;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;
public class ChatComponent extends TextWebSocketHandler {
List<WebSocketSession> sessionList = new ArrayList<>();
// 저장 - source - Override/Implements method
@Override // 연결이 성립된 이후 실행되는 함수
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
System.out.println("연결 생성 확인 : " + session);
sessionList.add(session);
}
@Override // 텍스트 메시지를 전달받았을 때 실행되는 함수
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
System.out.printf("메시지 받음 : [%s] : %s\n", session, message);
for(WebSocketSession ws : sessionList) { // 세션리스트에 들어가있는 모든 웹 소켓에게
ws.sendMessage(message); // 받은 메시지를 다시 보낸다 (== 클라이언트가 응답을 받았을 것이다)
}
}
@Override // 연결이 끊어졌을 때 실행되는 함수
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
System.out.println("연결 종료 : " + session);
sessionList.remove(session);
}
}
접속 이동 경로
함수 작성 없이 먼저 연결부터 확인해봐야 한다.
web.xml 에서 version은 3.0 이상이어야 한다. > WebSocket 지원이 3.0 이상 부터 가능
1. home.jsp에서 script 태그
const ws = new SockJS(cpath + '/chat')
2. ChatComponent 에서
afterConnectionEstablished가 작동하면
3. 콘솔창에서 연결 확인 메시지가 뜬다.
실시간으로 빠릿 빠릿 하게 통신이 되는걸 보니까 너무 재밌었다.
다음 번에는 이 웹소켓을 활용하여 채팅을 한 번 구현해 볼 생각이다.
'Spring' 카테고리의 다른 글
[Project] 실시간 1:1 채팅 (0) | 2024.10.10 |
---|---|
[Spring] WebSocket - 실시간 채팅 (0) | 2024.10.10 |
[Spring] HashMap json mapping (2) | 2024.10.10 |
[Spring] 매장 포스기 시스템 (1) | 2024.10.09 |
[Spring] RestController (1) | 2024.10.09 |