ChatTestProject๐
์์ ์ ๋ฆฌํ WebSocket์ผ๋ก ์ค์๊ฐ ์ฑํ ์ ๊ตฌํํ๋ ํ๋ก์ ํธ์ด๋ค.
๋๋ค์์ ์ค์ ํ์ฌ ๋ค์ด๊ฐ ํ n๋ช ๊ณผ ๋ํ๋ฅผ ํ๋ค.
https://steady-record.tistory.com/entry/WebSocket
ํ์ผ๊ตฌ์ฑ๐
์์ ํจํค์ง(ํด๋) | ํ์ ํจํค์ง(ํด๋) | ํ์ผ๋ช | ์ญํ |
src/main/java | com.test.controller | ChatController.java | ์๋ฒ์ ํด๋ผ์ด์ธํธ ๋ฌผ์ง์ ์ฐ๊ฒฐ |
com.test.server | ChatServer.java | ์๋ฒ | |
com.test.domain | Message.java | ๋ฉ์์ง๋ฅผ ๋ด๋ DTO | |
webapp/WEB-INF/views | index.jsp | ์ฑํ ์ ์ฅ ์ ํ์ด์ง | |
chat.jsp | ์ฑํ ํ์ด์ง |
ํ๊ฒฝ์ค์ ๐
์ด ํ๋ก์ ํธ์์๋ DB์์ ์ ํ์ง ์๊ธฐ์ ๋ฒ์ ๋ณ๊ฒฝ ๋ฐ ์์กด์ฑ ์ถ๊ฐ๋ง ์ค์ ํ๊ฒ ๋ค.
1. ๋ฒ์ ์ค์ - pom.xml
์๋ ๊ธ์ ์ฐธ๊ณ ํ์ฌ ์๋ฐ์ ์คํ๋ง ๋ฒ์ ์ ๋ณ๊ฒฝํ๋ค.
2. ์์กด์ฑ ์ถ๊ฐ - pom.xml
gson : ๊ตฌ๊ธ์์ ๋ง๋ josn ํ์ฑ ๋ผ์ด๋ธ๋ฌ๋ฆฌ
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.10.1</version>
</dependency>
3. ์ปดํฌ๋ํธ ์ค์บ - servlet-context.xml
์ง์ ์์ฑํ ํจ์ง๋ฆฌ๋ฅผ ์คํ๋ง์ด ์ค์บํ ์ ์๋๋ก ๋ฑ๋กํ๋ค.
<context:component-scan base-package="com.test.socket" />
<context:component-scan base-package="com.test.controller" />
<context:component-scan base-package="com.test.server" />
๊ตฌํ ์์ค
- ChatController.java
package com.test.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class ChatController {
@GetMapping(value = "/index.do")
public String index(Model model) {
return "index";
}
@GetMapping(value = "/chat.do")
public String chat(Model model) {
return "chat";
}
}
DB ์์ ์์ด ์๋ฒ์ ํด๋ผ์ด์ธํธ๊ฐ ์ํตํ ๋๋ ์ปจํธ๋กค๋ฌ๊ฐ ํ ์ผ์ด ์๋ค.
- Message.java
ํด๋ผ์ด์ธํธ์ ์๋ฒ ์ฌ์ด์์ ์ฃผ๊ณ ๋ฐ์ ๋ฐ์ดํฐ๋ฅผ DTO๋ก ํฌ์ฅํ๋ค. Lombok๋ฅผ ์ค์นํ์ง์์ getter, setter๋ฅผ ์์ฑํด์ฃผ์๋ค.
package com.test.domain;
//ํด๋ผ์ด์ธํธ, ์๋ฒ ๊ฐ์ ๋ฐ์ดํฐ
public class Message {
private String code; //์ํ์ฝ๋
private String sender; //๋ณด๋ด๋ ์ฌ๋
private String receiver; //๋ฐ๋ ์ฌ๋
private String content; //๋ํ ๋ด์ฉ
private String regdate; //๋ ์ง
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getSender() {
return sender;
}
public void setSender(String sender) {
this.sender = sender;
}
public String getReceiver() {
return receiver;
}
public void setReceiver(String receiver) {
this.receiver = receiver;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getRegdate() {
return regdate;
}
public void setRegdate(String regdate) {
this.regdate = regdate;
}
@Override
public String toString() {
return "Message [code=" + code + ", sender=" + sender + ", receiver=" + receiver + ", content=" + content
+ ", regdate=" + regdate + "]";
}
}
- ์ฑํ ๋ฐฉ ์ ์ฅํ๊ธฐ
index.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- chat</title>
<link rel="stylesheet" href="https://me2.do/5BvBFJ57">
</head>
<body>
<!-- index.jsp -->
<h1>WebSocket <small>chat</small></h1>
<div>
<div class="group">
<label>๋๋ค์</label>
<input type="text" name="name" id="name" class="short">
</div>
</div>
<div>
<button type="button" class="in">๋ค์ด๊ฐ๊ธฐ</button>
</div>
<script src="https://code.jquery.com/jquery-1.12.4.js" ></script>
<script>
$('.in').click(function() {
let name = $('#name').val();
if ($(event.target).data('name') != null && $(event.target).data('name') != '') {
name = $(event.target).data('name');
}
let child = window.open('/socket/chat.do', 'chat', 'width=405', 'height=510');
child.addEventListener('load', function() {
//์์์ฐฝ ๋ค ๋จ๊ณ ๋๋ฉด ๋ฐ์
child.connect(name);
});
//๋นํ์ฑํ
$('.in').css('opacity', .5).prop('disabled', true);
$('#name').prop('readOnly', true);
});
</script>
</body>
</html>
๋๋ค์์ ์ค์ ํ์ฌ ๋ค์ด๊ฐ๊ธฐ ๋ฒํผ์ผ๋ก ์ฑํ ๋ฐฉ์ ์ ์ฅํ ์ ์๋๋กํ๋ค.
์ฑํ ๋ฐฉ ํ์ด์ง๋ฅผ window.open์ผ๋ก ์ด๊ณ child๋ก ์ ์ฅํ๋ค.
child๊ฐ load ๋๋ฉด ์ฑํ ๋ฐฉํ์ด์ง๋ฅผ ์ฐ๊ฒฐํ๊ณ ๋ค์ด๊ฐ๊ธฐ ๋ฒํผ์ ๋นํ์ฑํํ๋ค.
- ์ฑํ ๋ฐฉ ๋์์ธ
chat.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- chat</title>
<link rel="stylesheet" href="https://me2.do/5BvBFJ57">
<style>
html, body {
padding: 0 !important;
margin: 0 !important;
background-color: #FFF !important;
display: block;
overflow: hidden;
}
body > div {
margin: 0;
padding: 0;
}
#main {
width: 400px;
height: 510px;
margin: 3px;
display: grid;
grid-template-rows: repeat(12, 1fr);
}
#header > h2 {
margin: 0px;
margin-bottom: 10px;
padding: 5px;
}
#list {
border: 1px solid var(--border-color);
box-sizing: content-box;
padding: .5rem;
grid-row-start: 2;
grid-row-end: 12;
font-size: 14px;
overflow: auto;
}
#msg {
margin-top: 3px;
}
#list .item {
font-size: 14px;
margin: 15px 0;
}
#list .item > div:first-child {
display: flex;
}
#list .item.me > div:first-child {
justify-content: flex-end;
}
#list .item.other > div:first-child {
justify-content: flex-end;
flex-direction: row-reverse;
}
#list .item > div:first-child > div:first-child {
font-size: 10px;
color: #777;
margin: 3px 5px;
}
#list .item > div:first-child > div:nth-child(2) {
border: 1px solid var(--border-color);
display: inline-block;
min-width: 100px;
max-width: 250px;
text-align: left;
padding: 3px 7px;
}
#list .state.item > div:first-child > div:nth-child(2) {
background-color: #EEE;
}
#list .item > div:last-child {
font-size: 10px;
color: #777;
margin-top: 5px;
}
#list .me {
text-align: right;
}
#list .other {
text-align: left;
}
#list .msg.me.item > div:first-child > div:nth-child(2) {
background-color: rgba(255, 99, 71, .2);
}
#list .msg.other.item > div:first-child > div:nth-child(2) {
background-color: rgba(100, 149, 237, .2);
}
#list .msg img {
width: 150px;
}
</style>
</head>
<body>
<!-- chat.jsp -->
<div id="main">
<div id="header"><h2>WebSocket <small>๋๋ค์</small></h2></div>
<div id="list">
</div>
<input type="text" id="msg" placeholder = "๋ํ ๋ด์ฉ์ ์
๋ ฅํ์ธ์.">
</div>
<script src="https://code.jquery.com/jquery-1.12.4.js" ></script>
</body>
</html>
- ์ ์ฅ ๋ฉ์์ง ๋์ฐ๊ธฐ
1. (ํด๋ผ์ด์ธํธ)์๋ฒ ์ฐ๊ฒฐ ๋ฐ ์๋ฒ๋ก ์ฌ์ฉ์ ์ ๋ณด ๋ณด๋ด๊ธฐ
chat.jsp
<script>
let name;
let ws;
const url = 'ws://localhost:8090/socket/chatserver.do';
function connect(name) {
window.name = name;
$('#header small').text(name);
//์๋ฒ์ ์ฐ๊ฒฐํ๊ธฐ > ์์ผ ์์ฑ
ws = new WebSocket(url);
ws.onopen = function(evt) {
log('์๋ฒ ์ฐ๊ฒฐ ์ฑ๊ณต');
let message = {
code: '1',
sender: window.name,
receiver: '',
content: '',
regdate: new Date().toLocaleString()
};
//jOSN ๋ฌธ์์ด๋ก ๋ณํ ํ ์ ์ก
ws.send(JSON.stringify(message));
print('', '๋ํ๋ฐฉ์ ์ฐธ์ฌํ์ต๋๋ค.' , 'me', 'state', message.regdate);
$('#msg').focus();
};
}//connect
const url = 'ws://localhost:8090/socket/chatserver.do';
์๋ฒ์์ ์ฐ๊ฒฐ์ ์ํ ์ฃผ์์ด๋ค. ์๋ฒ์์๋ @ServerEndpoint("/chatserver.do") ์ข ๋จ์ ์ ์ค์ ํด์ผํ๋ค.
ws = new WebSocket(url);
์๋ฒ ์ฐ๊ฒฐ
ws.onopen = function(evt) {
open ์ด๋ฒคํธ๋ก ํด๋ผ์ด์ธํธ๋ ์๋ฒ์ ์ฐ๊ฒฐ ์งํ ์ฌ์ฉ์์ ์ ๋ณด๋ฅผ ์๋ฒ์ ์ ๋ฌํ๋ค.
ํ๋กํ ์ฝ์ ์ด์ฉํ ๋ฉ์์ง ๋ณด๋ด๊ธฐ
์ฌ๋์ด ๋ค์ด์จ ์ํ ๋ฐ ๋ฉ์์ง๋ ws.send๋ก ์ ๋ฌํ๋ค.
์ด๋ค ์ฉ๋์ ๋ฉ์์ง์ธ์ง ์๋ฒ์ธก์์๋ ์๊ธฐ ํ๋ค๊ธฐ ๋๋ฌธ์ ๋ฉ์์ง์ ๊ท์น์ผ๋ก ๊ตฌ๋ถ์ง์ด ์ ์กํ๋ค.
๋ฉ์์ง์ ๊ท์น์ผ๋ก ์ซ์๋ ์ํ์ฝ๋๋ฅผ ๋ํ๋ด๊ณ ๊ทธ ์ํ์ฝ๋์ ๋ฐ๋ผ ๋ท ๋ด์ฉ์ ๊ตฌ๋ถ ์ง๋๋ค.
ํ๋กํ ์ฝ์ ํต์ ์ ์ฌ์ฉ๋๋ ๋ฉ์์ง์ ํ์๊ณผ ์๋ฏธ๋ฅผ ์ ์ํ๋ ๊ท
์น์ ์งํฉ์ผ๋ก, ์ฃผ๊ณ ๋ฐ๋ ๋ฉ์์ง์ ๊ตฌ์กฐ๋ฅผ ํต์ผํ์ฌ ์๋ฒ์ ํด๋ผ์ด์ธํธ ๊ฐ์ ์ํํ ํต์ ์ ์ง์ํ๊ธฐ ์ํด ํ๋กํ ์ฝ์ ์ฌ์ฉํ๋ค.
์ฌ๊ธฐ์๋ ๋ฉ์์ง์ ๊ท์น์ JSON ํ์์ผ๋ก ์ ์ํ๊ณ , ์ซ์๋ก ํํ๋ ์ํ์ฝ๋๋ฅผ ์ฌ์ฉํ์ฌ ๋ค์ํ ๋ฉ์์ง ์ ํ์ ๋ํ๋ธ๋ค.
- code : ์ํ์ฝ๋
- 1 : ์๋ก์ด ์ ์ ๊ฐ ๋ค์ด์ด
- 2: ๊ธฐ์กด ์ ์ ๊ฐ ๋๊ฐ
- 3: ๋ฉ์์ง ์ ๋ฌ
- 4: ์ด๋ชจํฐ์ฝ ์ ๋ฌ
- sender : ๋ณด๋ด๋ ์ ์ ๋ช
- receiver : ๋ฐ๋ ์ ์ ๋ช
- content : ๋ํ ๋ด์ฉ
- regdate : ๋ ์ง/์๊ฐ
ws.send(JSON.stringify(message));
message ๊ฐ์ฒด๋ฅผ JSON ํ์์ผ๋ก ๋ณํํ๊ณ , ์น ์์ผ์ ํตํด ์๋ฒ๋ก ์ ์กํ๋ค.
2. (์๋ฒ) ํด๋ผ์ด์ธํธ ๋ฉ์์ง ์์ ๋ฐ๊ธฐ ๋ฐ ์ ์กํ๊ธฐ
ChatServer.java
package com.test.server;
@ServerEndpoint("/chatserver.do")
public class ChatServer {
private static List<Session> sessionList = new ArrayList<Session>();
@OnOpen
public void handleOpen(Session session) {
sessionList.add(session);
checkSessionList(); //์ ์์ ํ์ธ
}
@OnMessage
public void handleMessage(String msg, Session session) {
System.out.println(msg);
Gson gson = new Gson();
Message message = gson.fromJson(msg, Message.class);
if (message.getCode().equals("1")) {
for (Session s : sessionList) {
if (s != session) {
try {
s.getBasicRemote().sendText(msg);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
//์ ์์๋ฅผ ํ์ธํ๋ ๋ฉ์๋
private void checkSessionList() {
System.out.println();
System.out.println("[Session List]");
for (Session session : sessionList) {
System.out.println(session.getId());
}
System.out.println();
}
}
@ServerEndpoint("/chatserver.do")
์น ์์ผ ํต์ ์ ์ํ ์๋ํฌ์ธํธ ํด๋์ค๋ก์, ํด๋ผ์ด์ธํธ์์ ์ฐ๊ฒฐ์ ๊ด๋ฆฌํ๊ณ ํต์ ์ ์ํํ๋ ๋ก์ง์ ํด๋น ํด๋์ค์ ์์ฑํ๋ค.
private static List<Session> sessionList = new ArrayList<Session>();
์๋ฒ์์๋ ์ ์ 1์ ์์ผ๊ณผ ์ ์ 2์ ์์ผ์ ๊ฐ๊ฐ ๊ด๋ฆฌ๋ฅผ ํด์ผํ๋ค. 1๋ช ์ด์์ด ์ ์ํ๊ธฐ์ arraylist๋ก ๊ด๋ฆฌํ๋ ๊ฒ์ด ํธํ๋ค.
websocket์ session์ ์ฑํ ์ ์ ์ํ ํด๋ผ์ด์ธํธ์ ์ํ ๊ด๋ฆฌ๋ฅผ ์ํด ํด๋ผ์ด์ธํธ๊ฐ ์ ์ํ์ ๋ list์ session์ ์ถ๊ฐํ๋ค.
@OnOpen
public void handleOpen(Session session) {
WebSocket ์ฐ๊ฒฐ์ด ์ด๋ฆด ๋ ์๋์ผ๋ก ํธ์ถ๋๋ค.
sessionList.add(session);
์ ์ํ ํด๋ผ์ด์ธํธ์ ์ธ์ ์ ์ ์ฅํ๋ค.
@OnMessage
public void handleMessage(String msg, Session session) {
ํด๋ผ์ด์ธํธ๋ก๋ถํฐ ๋ฉ์์ง๋ฅผ ์์ ํ ๋ ํธ์ถ๋๋ค.
Gson gson = new Gson();
Gson : JSON ํ์์ ๋ฌธ์์ด์ ์๋ฐํด๋์ค ๊ฐ์ฒด๋ก ๋ณํํ๋ค.
์์์ ํด๋ผ์ด์ธํธ๊ฐ msg๋ฅผ JSON์ ์ ์ก์ ํ์์ผ๋ฉฐ, ์๋ฐํด๋์ค์์ ํด์๊ฐ๋ฅํ๋๋ก ๋ค์ ์๋ฐํด๋์ค ๊ฐ์ฒด๋ก ๋ณํํ๋ค.
Message message = gson.fromJson(msg, Message.class);
SON ํ์์ ๋ฌธ์์ด(msg)์ Gson ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ฌ Java ๊ฐ์ฒด(Message ํด๋์ค์ ์ธ์คํด์ค)๋ก ๋ณํํ๋ค.
if (message.getCode().equals("1")) {
for (Session s : sessionList) {
if (s != session) {
try {
s.getBasicRemote().sendText(msg);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
๋ชจ๋ ์ ์์ ์ค์์ ๋ฐฉ๊ธ ๋ฉ์์ง๋ฅผ ๋ณด๋ธ ์ธ์
์ ์ ์ธํ๊ณ ๋๋จธ์ง ์ธ์
์ ๊ฒ์ํ๋ค.
๋ณธ์ธ์ด์ธ์ ์ธ์
(์์ผ)์๊ฒ ํ์ฌ ์ ์์๋ฅผ ์๋ฆฌ๋ ๋ฉ์์ง๋ฅผ ์ ๋ฌํ๋ค.
getBasicRemote() : ์ธ์ ๊ณผ ๊ด๋ จ๋ ์์ผ์ ๋ฐํํ์ฌ
sendText() : ๋ฉ์์ง๋ฅผ ํด๋ผ์ด์ธํธ๋ก ๋ณด๋ธ๋ค.
3. (ํด๋ผ์ด์ธํธ) ์๋ด ๋ฉ์์ง ํ๋ฉด์ ์ถ๋ ฅํ๊ธฐ
chat.jsp
<script>
let name;
let ws;
const url = 'ws://localhost:8090/socket/chatserver.do';
function connect(name) {
window.name = name;
$('#header small').text(name);
ws = new WebSocket(url);
ws.onopen = function(evt) {
let message = {
code: '1',
sender: window.name,
receiver: '',
content: '',
regdate: new Date().toLocaleString()
};
//jOSN ๋ฌธ์์ด๋ก ๋ณํ ํ ์ ์ก
ws.send(JSON.stringify(message));
print('', '๋ํ๋ฐฉ์ ์ฐธ์ฌํ์ต๋๋ค.' , 'me', 'state', message.regdate);
$('#msg').focus();
};
//์๋ฒ์์ ํด๋ผ์ด์ธํธ์๊ฒ ์ ๋ฌํ ๋ฉ์์ง
ws.onmessage = function(evt) {
let message = JSON.parse(evt.data);
if (message.code == '1') {
print('', `[\${message.sender}]๋์ด ๋ค์ด์์ต๋๋ค.`, 'other', 'state', message.regdate);
}
}
}//connect
function log(msg) {
console.log(`[\${new Date().toLocaleTimeString()}] \${msg}`);
}
//๋ํ์ฐฝ ์ถ๋ ฅ ๋ฉ์๋
function print(name, msg, side, state, time) {
let temp = `
<div class="item \${state} \${side}">
<div>
<div>\${name}</div>
<div>\${msg}</div>
</div>
<div>\${time}</div>
</div>`;
$('#list').append(temp);
//์๋ก์ด ๋ด์ฉ์ด ์ถ๊ฐ๋๋ฉด ์คํฌ๋กค์ ๋ฐ๋ฅ์ผ๋ก ๋ด๋ฆฐ๋ค.
scrollList();
}
function scrollList() {
$('#list').scrollTop($('#list').outerHeight() + 300);
}
</script>
onmessage ์ด๋ฒคํธ๋ก ์๋ฒ์์ ์ ๋ฌ๋ฐ์ ๋ฉ์์ง๋ฅผ ์ถ๋ ฅํ๋ค.
์ถ๋ ฅํ์์ ๋ฉ์๋๋ฅผ ๋ง๋ค์ด ์ถ๋ ฅ์ด ํ์ํ ๋ ์์์ ๋ง์ถฐ ์ถ๋ ฅํ๋ค.
- ํด์ฅ ๋ฉ์์ง ๋์ฐ๊ธฐ
๋ํ์ฐฝ์ ๋ซ์์ ๋ ํด์ฅํ๋ค๊ณ ๊ฐ์ ํ๋ค.
1. (ํด๋ผ์ด์ธํธ) ํด์ฅํ ์ ์ ์ ๋ณด ์๋ฒ๋ก ์ ์กํ๊ธฐ
chat.jsp
<script>
$(window).on('beforeunload', function() {
disconnect();
});
function disconnect() {
//๋ํ๋ฐฉ์์ ๋๊ฐ๋ฉด, ๋ค๋ฅธ ์ฌ๋์๊ฒ ์๋ด๋ฉ์์ง๋ฅผ ๋ณด๋ธ๋ค.
let message = {
code: '2',
sender: window.name,
receiver: '',
content: '',
regdate: new Date().toLocaleString()
};
//jOSN ๋ฌธ์์ด๋ก ๋ณํ ํ ์ ์ก
ws.send(JSON.stringify(message));
}
</script>
beforeunload
์ฐฝ์ด ๋ซํ๊ธฐ ๋ฐ๋ก ์ง์ ์ ๋ฐ์ํ๋ค.
๋ํ๋ฐฉ์์ ๋๊ฐ๋ฉด, ๋ค๋ฅธ ์ฌ๋๋ค์๊ฒ ์๋ด๋ฉ์์ง๋ฅผ ๋ณด๋ด๊ธฐ ์ํด ์๋ฒ๋ก ๋ณด๋ผ ๋ฉ์์ง๋ฅผ ์์ฑํ๋ค.
๋ํ๋ฐฉ์์ ๋๊ฐ๋ค๋ ์๋ฏธ๋ก ์ฝ๋ 2๋ฒ์ผ๋ก ์ ํ๋ค.
๋ฐฐ์ด๋ก ์์ฑํ ๋ฉ์์ง๋ฅผ JSON ๋ฌธ์์ด๋ก ๋ณํ ํ ์๋ฒ๋ก ์ ์กํ๋ค.
2. (์๋ฒ) ํด๋ผ์ด์ธํธ ๋ฉ์์ง ์ก์์ ๋ฐ ์ธ์ ์ ๊ฑฐ
package com.test.server;
@ServerEndpoint("/chatserver.do")
public class ChatServer {
@OnOpen
public void handleOpen(Session session) {
sessionList.add(session);
checkSessionList(); //์ ์์ ํ์ธ
clearSessionList();
}
@OnMessage
public void handleMessage(String msg, Session session) {
System.out.println(msg);
Gson gson = new Gson();
Message message = gson.fromJson(msg, Message.class);
if (message.getCode().equals("1")) { //์๋๋ฐฉ ๋ํ๋ฐฉ ์
์ฅ
for (Session s : sessionList) {
if (s != session) {
try {
s.getBasicRemote().sendText(msg);
} catch (Exception e) {
e.printStackTrace();
}
}
}
} else if (message.getCode().equals("2")) {
sessionList.remove(session);
for (Session s : sessionList) {
try {
s.getBasicRemote().sendText(msg);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
//์ ์์๋ฅผ ํ์ธํ๋ ๋ฉ์๋
private void checkSessionList() {
System.out.println();
System.out.println("[Session List]");
for (Session session : sessionList) {
System.out.println(session.getId());
}
System.out.println();
}
//์์ ์ฑ์ ์ํ ๋ฉ์๋ : ์ฐ๊ฒฐ์ด ๋์ด์ง ์ธ์
์ด ์์ผ๋ฉด ์ธ์
๋ฆฌ์คํธ์์ ์ ๊ฑฐํ๋ค.
private void clearSessionList() {
//List ๊ณ์ด์ ์ปฌ๋ ์
์ ํฅ์๋ for๋ฌธ ๋ด์์ ์์ ์ถ๊ฐ/์ญ์ ํ๋ ํ๋์ ํ ์ ์๋ค.
//๊ฐ๋ฅํ ๋ฐฉ๋ฒ์ 1. ์ผ๋ฐ forans, 2. Interator ๋ฐฉ๋ฒ์ด ์๋ค.
Iterator<Session> iter = sessionList.iterator();
while(iter.hasNext()) {
if(!(iter.next()).isOpen()) {
//ํน์ ์ฐ๊ฒฐ์ด ๋์ด์ง ์ธ์
์ด ์์ผ๋ฉด ๋ฆฌ์คํธ์์ ์ ๊ฑฐํ๋ค.
iter.remove();
}
}
}
}
clearSessionList()
์ฐ๊ฒฐ์ด ๋์ด์ง ์ธ์ ์ด ์์ผ๋ฉด ์ธ์ ๋ฆฌ์คํธ์์ ์ ๊ฑฐํ๋ ๋ฉ์๋์ด๋ค.
์๋๋ฐฉ์ด ๋๊ฐ๋ค๋ ์๋ฏธ์ธ ์ฝ๋ 2๋ฒ์ ์์ ๋ฐ์์ ๋, ์ธ์ ์ ์ ๊ฑฐํ์ง๋ง, ์์ ์ฑ์ ์ํด ์น์์ผ์ด ์ด๋ ธ์ ๋, ๋ค์ ํ๋ฒ ํ์ธํ๋ค.
์ฝ๋ 2๋ฒ์ผ๋ก ๋ฉ์์ง๋ฅผ ์์ ๋ฐ์์ ๋,
1. session ์ ๊ฑฐ
2. ๋๋จธ์ง ๋ชจ๋ ์ฌ๋์๊ฒ ์ ์ ํด์ฅ ๋ฉ์์ง๋ฅผ ๋ณด๋ธ๋ค.
3. (ํด๋ผ์ด์ธํธ) ์๋ด ๋ฉ์์ง ํ๋ฉด์ ์ถ๋ ฅํ๊ธฐ
chat.jsp
<script>
let name;
let ws;
const url = 'ws://localhost:8090/socket/chatserver.do';
function connect(name) {
window.name = name;
$('#header small').text(name);
ws = new WebSocket(url);
ws.onopen = function(evt) {
let message = {
code: '1',
sender: window.name,
receiver: '',
content: '',
regdate: new Date().toLocaleString()
};
ws.send(JSON.stringify(message));
print('', '๋ํ๋ฐฉ์ ์ฐธ์ฌํ์ต๋๋ค.' , 'me', 'state', message.regdate);
$('#msg').focus();
};
ws.onmessage = function(evt) {
let message = JSON.parse(evt.data);
console.log(message);
if (message.code == '1') {
print('', `[\${message.sender}]๋์ด ๋ค์ด์์ต๋๋ค.`, 'other', 'state', message.regdate);
} else if (message.code == '2') {
print('', `[\${message.sender}]๋์ด ๋๊ฐ์ต๋๋ค.`, 'other', 'state', message.regdate);
}
}
}//connect
function log(msg) {
console.log(`[\${new Date().toLocaleTimeString()}] \${msg}`);
}
function print(name, msg, side, state, time) {
let temp = `
<div class="item \${state} \${side}">
<div>
<div>\${name}</div>
<div>\${msg}</div>
</div>
<div>\${time}</div>
</div>`;
$('#list').append(temp);
//์๋ก์ด ๋ด์ฉ์ด ์ถ๊ฐ๋๋ฉด ์คํฌ๋กค์ ๋ฐ๋ฅ์ผ๋ก ๋ด๋ฆฐ๋ค.
scrollList();
}
$(window).on('beforeunload', function() {
disconnect();
});
function disconnect() {
let message = {
code: '2',
sender: window.name,
receiver: '',
content: '',
regdate: new Date().toLocaleString()
};
ws.send(JSON.stringify(message));
}
//๋ํ ์คํฌ๋กค ์ด๋ฒคํธ
function scrollList() {
$('#list').scrollTop($('#list').outerHeight() + 300);
}
</script>
print ๋ฉ์๋๋ก ๋๊ฐ ์ ์ ์ ์ด๋ฆ์ผ๋ก ํด์ฅ ๋ฉ์์ง๋ฅผ ์ถ๋ ฅํ๋ค.
- ์ฑํ ํ๊ธฐ
1. (ํด๋ผ์ด์ธํธ) ์๋ฒ๋ก ๋ฉ์์ง ์ ์กํ๊ธฐ
chat.jsp
<script>
$('#msg').keydown(function(evt) {
//์ํฐ๋ฅผ ๋๋ ์ ๋, ์
๋ ฅํ ๋ํ ๋ด์ฉ์ ์๋ฒ๋ก ์ ๋ฌํ๊ธฐ
if (evt.keyCode == 13) { //์ํฐ
let message = {
code: '3',
sender: window.name,
receiver: '',
content: $('#msg').val(),
regdate: new Date().toLocaleString()
};
ws.send(JSON.stringify(message));
$('#msg').val('').focus();
print(window.name, message.content, 'me', 'msg', message.regdate);
}
});
</script>
์ํฐ์ ์์คํค์ฝ๋ ๊ฐ์ผ๋ก ์ํฐ๋ฅผ ์ธ์ํ์ฌ ๋ฉ์์ง๋ฅผ ์๋ฒ๋ก ๋ณด๋ธ๋ค.
์ฑํ ๋ฉ์์ง ์ก๋ถ๋ ์ฝ๋ 3๋ฒ์ผ๋ก ์ง์ ํ๋ค.
์๋ฒ๋ก ๋ฉ์์ง๋ฅผ ๋ณด๋ธ ๋ค msg ํ ์คํธ ๋ฐ์ค๋ ๋ค์ ์ ๋ ฅ์ ์ํด ๋น์นธ์ผ๋ก ๋๊ณ ํฌ์ปค์ค๋ฅผ ๋ง์ถ๋ค.
๋ณด๋ธ ๋ฉ์์ง๋ ๋ฐ๋ก ๋ณธ์ธ์ ํ๋ฉด์์ ์ถ๋ ฅํ๋ค.
2. (์๋ฒ) ํด๋ผ์ด์ธํธ ๋ฉ์์ง ์ก์์
ChatServer.java
package com.test.server;
@ServerEndpoint("/chatserver.do")
public class ChatServer {
@OnOpen
public void handleOpen(Session session) {
sessionList.add(session);
checkSessionList(); //์ ์์ ํ์ธ
clearSessionList();
}
@OnMessage
public void handleMessage(String msg, Session session) {
System.out.println(msg);
Gson gson = new Gson();
Message message = gson.fromJson(msg, Message.class);
if (message.getCode().equals("1")) { //์๋๋ฐฉ ๋ํ๋ฐฉ ์
์ฅ
for (Session s : sessionList) {
if (s != session) {
try {
s.getBasicRemote().sendText(msg);
} catch (Exception e) {
e.printStackTrace();
}
}
}
} else if (message.getCode().equals("2")) {
sessionList.remove(session);
for (Session s : sessionList) {
try {
s.getBasicRemote().sendText(msg);
} catch (Exception e) {
e.printStackTrace();
}
}
} else if (message.getCode().equals("3")) {
//๋ณด๋ธ ์ฌ๋๋นผ๊ณ ๋๋จธ์ง ์ฌ๋์๊ฒ ์ ๋ฌํ๋ค.
for (Session s : sessionList) {
if (s != session) {
try {
s.getBasicRemote().sendText(msg);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
}
3. (ํด๋ผ์ด์ธํธ) ์ฑํ ์ถ๋ ฅํ๊ธฐ
chat.jsp
<script>
function connect(name) {
ws.onmessage = function(evt) {
let message = JSON.parse(evt.data);
console.log(message);
if (message.code == '1') {
print('', `[\${message.sender}]๋์ด ๋ค์ด์์ต๋๋ค.`, 'other', 'state', message.regdate);
} else if (message.code == '2') {
print('', `[\${message.sender}]๋์ด ๋๊ฐ์ต๋๋ค.`, 'other', 'state', message.regdate);
} else if (message.code == '3') {
print(message.sender, message.content, 'other', 'msg', message.regdate);
}
}
}//connect
</script>
- ์ด๋ชจํฐ์ฝ(์ด๋ฏธ์ง) ๋ณด๋ด๊ธฐ
'/'๋ฅผ ์์ ์ ๋ ฅํ๊ณ ํ์ผ๋ช ์ ์ ์ผ๋ฉด ํด๋น ์ด๋ฏธ์ง๊ฐ ์ ์ก๋๋ค.
1. (ํด๋ผ์ด์ธํธ) ์๋ฒ๋ก ๋ฉ์์ง ์ ์กํ๊ธฐ
chat.jsp
<script>
$('#msg').keydown(function(evt) {
//์ํฐ๋ฅผ ๋๋ ์ ๋, ์
๋ ฅํ ๋ํ ๋ด์ฉ์ ์๋ฒ๋ก ์ ๋ฌํ๊ธฐ
if (evt.keyCode == 13) { //์ํฐ
let message = {
code: '3',
sender: window.name,
receiver: '',
content: $('#msg').val(),
regdate: new Date().toLocaleString()
};
//์ ์ก๋ฉ์์ง '/'๋ก ์์ํ๋ฉด ์ด๋ชจํฐ์ฝ ์ ์ก์ผ๋ก ์ค์ ํ๋ค.
if ($('#msg').val().startsWith('/')) {
message.code = '4';
}
ws.send(JSON.stringify(message));
$('#msg').val('').focus();
if (message.code == '3') {
print(window.name, message.content, 'me', 'msg', message.regdate);
} else if (message.code == '4') {
printEmoticon(window.name, message.content, 'me', 'msg', message.regdate);
}
}
});
//์ด๋ชจํฐ์ฝ ์ถ๋ ฅ ๋ฉ์๋
function printEmoticon(name, msg, side, state, time) {
let temp = `
<div class="item \${state} \${side}">
<div>
<div>\${name}</div>
<div style = "background-color:#fff; boarder:0;"><img src="/socket/resources/emoticon/\${msg}.png"></div>
</div>
<div>\${time}</div>
</div>
`;
$('#list').append(temp);
//์๋ก์ด ๋ด์ฉ์ด ์ถ๊ฐ๋๋ฉด ์คํฌ๋กค์ ๋ฐ๋ฅ์ผ๋ก ๋ด๋ฆฐ๋ค. (์ด๋ฏธ์ง ๋ก๋ฉ์ด ์๊ฐ์ด ์์๋์ 0.1์ด์ ์๊ฐ์ฐจ๋ฅผ ๋๋ค.)
setTimeout(scrollList, 100);
}
</script>
2. (์๋ฒ) ํด๋ผ์ด์ธํธ ๋ฉ์์ง ์ก์์
ChatServer.java
package com.test.server;
@ServerEndpoint("/chatserver.do")
public class ChatServer {
@OnOpen
public void handleOpen(Session session) {
sessionList.add(session);
checkSessionList(); //์ ์์ ํ์ธ
clearSessionList();
}
@OnMessage
public void handleMessage(String msg, Session session) {
System.out.println(msg);
Gson gson = new Gson();
Message message = gson.fromJson(msg, Message.class);
if (message.getCode().equals("1")) { //์๋๋ฐฉ ๋ํ๋ฐฉ ์
์ฅ
for (Session s : sessionList) {
if (s != session) {
try {
s.getBasicRemote().sendText(msg);
} catch (Exception e) {
e.printStackTrace();
}
}
}
} else if (message.getCode().equals("2")) {
sessionList.remove(session);
for (Session s : sessionList) {
try {
s.getBasicRemote().sendText(msg);
} catch (Exception e) {
e.printStackTrace();
}
}
} else if (message.getCode().equals("3")) { //์๋๋ฐฉ ๋ฉ์์ง ์ ์ก
//๋ณด๋ธ ์ฌ๋๋นผ๊ณ ๋๋จธ์ง ์ฌ๋์๊ฒ ์ ๋ฌํ๋ค.
for (Session s : sessionList) {
if (s != session) {
try {
s.getBasicRemote().sendText(msg);
} catch (Exception e) {
e.printStackTrace();
}
}
}
} else if (message.getCode().equals("4")) { //์๋๋ฐฉ ๋ฉ์์ง ์ ์ก
for (Session s : sessionList) {
if (s != session) {
try {
s.getBasicRemote().sendText(msg);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
}
3. (ํด๋ผ์ด์ธํธ) ์ฑํ ์ถ๋ ฅํ๊ธฐ
chat.jsp
<script>
function connect(name) {
ws.onmessage = function(evt) {
let message = JSON.parse(evt.data);
console.log(message);
if (message.code == '1') {
print('', `[\${message.sender}]๋์ด ๋ค์ด์์ต๋๋ค.`, 'other', 'state', message.regdate);
} else if (message.code == '2') {
print('', `[\${message.sender}]๋์ด ๋๊ฐ์ต๋๋ค.`, 'other', 'state', message.regdate);
} else if (message.code == '3') {
print(message.sender, message.content, 'other', 'msg', message.regdate);
} else if (message.code == '4') {
printEmoticon(message.sender, message.content, 'other', 'msg', message.regdate);
}
}
}//connect
</script>
'Spring' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Spring] WebSocket ๊ธฐ์ด ์์ (0) | 2023.12.01 |
---|---|
[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 |