2024. 6. 29. 13:57ㆍ· LANGUAGE/└ Java
환경 : Spring Tool Suite4
- 창마다 새로운 사용자로 인식하게끔 설정하여, 그룹채팅의 효과를 이해해보자
- 브로드캐스팅을 통해 모두에게 메세지가 전송되도록 구현!
소켓 생성
- GroupWebSocketServer.java
/**
* 접속한 사용자들을 어떻게 관리할 것인가?
* - 접속한 모든 사용자에게 메세지를 보내고 싶다면 사용자 정보를 저장
* - 저장소를 Set<WebSocketSession> 형태로 생성
* */
@Slf4j
@Service
public class GroupWebSocketServer extends TextWebSocketHandler{
//사용자의 정보를 저장할 저장소 생성
//private Set<WebSocketSession> users = new HashSet<>();//HashSet은 동기화 안 됨(자물쇠 없음)
//private Set<WebSocketSession> users = Collections.synchronizedSet(new HashSet<>());//자물쇠 추가
private Set<WebSocketSession> users = new CopyOnWriteArraySet<>();//동기화 됨(자물쇠 있음)
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
users.add(session);
log.debug("사용자 접속! 현재 사용자 {}명", users.size());
}
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
users.remove(session);
log.debug("사용자 접속 종료! 현재 사용자 {}명", users.size());
}
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
//사용자가 메세지를 보내면 어떻게 할까?
//- 사용자가 보낸 메세지를 저장소에 있는 모든 사용자에게 전송
//- 메세지는 조작을 해도 되고 있는 그대로 전송해도 된다
//전체에게 메세지를 전송(broadcast)
for(WebSocketSession user : users) {
user.sendMessage(message);
}
}
}
(+) 사용자의 정보를 저장할 저장소를 생성하기 위해 Collection으로 받아야 한다.
Set, Map, List 중 Set을 사용할 것임!
HashSet의 경우 동기화가 되지 않으므로 사용할 수 없다.
(+) Collections.synchronizedSet(new HashSet<>());
위의 토드는 동기화된 컬렉션을 생성하는 코드이다.
이 코드는 HashSet 컬렉션을 생성한 후 Collections 유틸리티 클래스의 synchronizedSet 메소드를 사용하여 HashSet을 동기화된 Set으로 래핑하는 것이다. 따라서 원래부터 동기화가 되는 것이 아닌 한 번 단계를 거쳐 동기화 기능을 부여했다고 볼 수 있다.
(+) CopyOnWriteArraySet<>(); 따라서 원래부터 동기화가 되는 이 메소드를 사용한다.
(+) 전체 사용자에게 메세지를 전송하기 위하여 for문을 활용하여 브로드캐스트 한다.
소켓 등록
- WebSocketServerConfiguration.java
/**
* 웹소켓과 관련된 설정을 작성하는 파일
* 이미 등록해둔 웹소켓 서버들을 가져와서 추가적인 설정을 한 뒤 활성화
* */
@EnableWebSocket//웹소켓을 사용할 것임을 표시(활성화)
@Configuration//설정파일임을 표시
public class WebSocketServerConfiguration implements WebSocketConfigurer {
@Autowired
private GroupWebSocketServer groupWebSocketServer;
@Override
public void registerWebSocketHandlers (WebSocketHandlerRegistry registry) {
//SockJS를 사용하도록 설정하며 등록
//[1] 웹소켓을 지원하지 않는 브라우저는 유사기술로 웹소켓처럼 구현해줌
//(유사기술은 pulling, long-pulling과 같은 기술을 말함)
//[2] 주소를 http로 사용 가능하며, 아무나 들어오지 못하도록 ws 주소가 변함
//[3] 접속자에 대한 컴팩트한 관리가 가능하다(heartbeat 핑)
registry.addHandler(groupWebSocketServer, "/ws/group")
.withSockJS();
}
}
페이지 등록
- PageController.java
@Controller
@RequestMapping("/page")
public class PageController {
@RequestMapping("/group")
public String group() {
return "group";
}
}
- group.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!-- javascript toast library -->
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/toastify-js/src/toastify.min.css">
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/toastify-js"></script>
<!-- sockjs cdn -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/sockjs-client/1.6.1/sockjs.min.js"></script>
<h1>그룹채팅 예제</h1>
<button class="btn-connect">연결</button>
<button class="btn-disconnect">종료</button>
<hr>
<input type="text" class="text-input" placeholder="메세지 작성">
<button class="btn-send">전송</button>
<div class="chat-wrapper"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<script type="text/javascript">
$(function(){
$(".btn-connect").click(function(){
window.socket = new SockJS("${pageContext.request.contextPath}/ws/group");
//연결 완료 시 해야할 작업들을 "콜백 함수"로 설정
window.socket.onmessage = function(e){
var area = $("<div>").text(e.data);
$(".chat-wrapper").append(area);
}
});
$(".btn-disconnect").click(function(){
window.socket.close();
});
//전송버튼을 누르면 입력한 메세지가 있는 경우 서버에 전송
$(".btn-send").click(function(){
var text = $(".text-input").val();//입력창의 입력값을 불러온다
if(text.length == 0) return;//입력값이 없으면 중지한다
window.socket.send(text);//서버로 입력값을 전송한다
$(".text-input").val("");//입력창의 입력값을 삭제한다
});
});
</script>
(+) 사용자가 작성한 내용이 chat-wrapper 클래스의 부분에 보여지고, input 창에 남은 내용은 지워주도록 구현. (이런 부분도 코드로 처리해줘야 한다는 사실......)
출력 결과
- 왼쪽 사용자가 글 작성
- 오른쪽 사용자가 글 작성
개인 공부 기록용입니다:)
'· LANGUAGE > └ Java' 카테고리의 다른 글
[ Java / Socket ] JSON을 이용하여 소켓 통신 (비회원 채팅, 익명채팅) (0) | 2024.06.30 |
---|---|
Heartbeat, Live Ping (0) | 2024.06.29 |
[ Java / Socket ] 서버/클라이언트 통신 및 토스트 메세지 띄워보기 (0) | 2024.06.29 |
[ Java / Socket ] 웹 소켓 서버 생성 / 접속 / 접속종료 (0) | 2024.06.29 |
[ Java ] 내장객체로 비.암(비밀번호 암호화 하기) (0) | 2024.06.25 |