Back-End/웹소켓
웹소켓 #2. 본인에게 알림 보내기
luminous_dev
2025. 2. 18. 19:13
spring-boot-starter-websocket
웹소켓은 클라이언트가 refresh 되거나 페이지 이동이 일어나면 자동으로 끊어지게 됨
그런 상황 막으려면 popup 등의 방법을 사용해야 함
WebSocket 라이브러리 + jsp/jstl 라이브러리
index.html
<%@ 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>Insert title here</title>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<style>
#popup{
display : none;
position : absolute;
width : 200px;
height : 50px;
border : 1px solid black;
bottom : 1%;
right : 1%;
}
div.bg{
width : 90%;
height : 15px;
border : 1px solid gray;
top : 10%;
left : 4%;
position : absolute;
border-radius : 5px;
/* 모서리 둥글게 */
}
div.bar{
width : 0%;
height : 15px;
background-color: green;
border-radius : 3px;
text-align: center;
font-size : 12px;
font-weight : 600;
}
</style>
</head>
<body>
<button onclick="socketOn()">웹소켓 연결</button>
<button onclick="sendMsg('start')">다운로드 시작</button>
<button onclick="disConn()">연결 끊기</button>
<div id = "popup">
<div id = "msg">
<div class="bg">
<div class = "bar">0%</div>
<!-- 몇퍼센트 완성되었는지 확인 -->
<!-- 쿠폰 5만건 - 비동기 - 계속 빙빙 돔 - 관리자는 왜 그러지?하면서 발송/ 새로고침 계속 함. 5번이나 똑같은 문자가 감 - ajax-->
</div>
</div>
</div>
</body>
<script>
var webSocket = null;
</script>
</html>
내장 톰캣 (spring boot app)으로는 사용이 불가함
(외장에서는 WS 프로토콜을 받지 못해서인데, SocketJs를 사용하면 쓸수 있음)
SocketJS : WebSocket이 제대로 동작하지 않을 때 폴백(fallback)을 제공하는 라이브러리
script 및 컨트롤러
웹소켓 연결 SocketOn()
오버라이드가 되는 것은 4가지
1. 웹소켓 켜질 대
2. 웹소켓 꺼질 때
3. 무엇을 보낼 때
4. 무엇을 받을 때
자바 스크립트는 오버라이드가 안되기 때문에 직접 만들어야 함
<script>
function socketOn(){
var url = "ws://localhost:8080/websocket_practice/chat";//url에 location.href 넣어도 되는지 확인
webSocket = new WebSocket(url);
//1. 웹소켓 연결됐을 때 (http와 달리 client <= server)
webSocket.onopen = function(evt){
console.log('웹소켓 연결',evt);
}
//2.웹소켓 끊어졌을 때
webSocket.onclose = function (evt){
console.log('웹소켓 종료',evt);
}
//3.메시지 받았을 때
webSocket.onmessage = function (evt){
console.log('메세지 수신',evt);
$('#popup').show(); //display는 show와 hide로 보여주고 숨길 수도 있다.
$('div.bar').html(evt.data);
$('div.bar').css({'width': evt.data});
if($('div.bar').html() == '100%') {
setTimeout(function () {
alert('다운로드 완료!');
$('#popup').hide();
}, 10);
}
}
<controller>
기본 세팅
@ServerEndpoint(value = "/chat")
public class websocketController {
Logger logger = LoggerFactory.getLogger(getClass());
value 안에는 요청
@ServerEndpoint
: WebSocket 서버 엔드포인트(서버에서 클라이언트의 요청을 처리하는 URL 경로)를 정의하는 어노테이션
1. 웹소켓 켜질 때 @OnOpen
2. 웹소켓 닫힐 때 @OnClose
3. 에러 났을 때 @OnError
4. 서버에서 메세지가 도착했을 때 @OnMessage
@ServerEndpoint(value = "/chat")
public class websocketController {
Logger logger = LoggerFactory.getLogger(getClass());
@OnOpen
public void onOpen(Session session) {
logger.info("접속한 세션 ID : "+session.getId());
}
@OnClose
public void onClose(Session session) {
logger.info("종료한 세션 ID : "+session.getId());
}
@OnError
public void onError(Session session, Throwable error) {
logger.info("에러난 세션 ID : "+session.getId());
logger.info(error.getMessage());
}
}
메시지 전달 및 받는 흐름
1. (jsp단) 클라이언트 > 서버
jsp의 function sendMsg(msg){ webSocket.send(msg);}에서 서버로 누군가에게 보낼 메시지 전달
2. (컨트롤러 단) jsp에서 클라이언트에서 서버로 전달받은 메시지 있으면 @OnMessage로 받음
(이건 내가 실제로 받은 메시지를 처리하는 것이 아닌, 내가 보낸 메시지를 서버가 받아서 OnMessage임)
3. (컨트롤러 단) sendMsg 메서드로 받은 메시지를 서버에서 메시지 받을 세션에 메시지 전달
4.(jsp단) webSocket.onmessage로 서버에서 보낸 메시지를 받음
<script>
알림 받을 곳에 메세지 보내기
//웹소켓 메시지 보내기(client -> server)
function sendMsg(msg){
webSocket.send(msg);
}
<controller>
@OnMessage는 클라이언트로부터 서버가 jsp의 sendMsg()함수로 메시지를 받은 상황
@OnMessage
public void onMessage(String message, Session session) throws Exception {
logger.info(session.getId()+"가 보낸 메시지 : "+message);
for (int i=1; i<=100;i++){
Thread.sleep(50); //0.1초마다 1씩 늘어나게
sendMsg(session,i+"%");
//WebSocket 연결이 활성화된 세션을 통해 특정 메시지를 클라이언트로 전송하는 메서드
}
}
//서버 > 클라이언트
private void sendMsg(Session session, String message) throws Exception {
session.getBasicRemote().sendText(message); //WebSocket 세션을 통해 메시지를 전송하는 역할
}