고래씌
[Spring] 10-4. 채팅방 메세지 통신 (F5를 누르지않아도 바로 생성되도록 작업) 본문
1. 채팅방 메세지 실시간 전송(F5를 누르지않아도 바로 생성되도록 작업)
☞ 메시지를 db에 성공적으로 저장했다면, 전달받은 메시지를 같은방에 접속중인 클라이언트들에게 전달
☞ ChatWebSocket.java에 추가
☞ public void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {} 메소드 안에 추가
☞ 참여한 인원이 중복되지 않도록 DB에 제약조건 추가
ALTER TABLE CHAT_ROOM_JOIN ADD PRIMARY KEY(USER_NO, CHAT_ROOM_NO); |
▶ ChatWebSocket.java
/* 클라이언트로부터 메시지(message)가 도착했을 시 실행되는 함수 */
@Override
public void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
// TextMessage : 웹소켓을 이용해 전달된 데이터(텍스트)가 담겨있는 객체
// payload : 전송되는 데이터(JSON객체로 전달받음)
log.info("전달된 메시지{}", message.getPayload());
// JackSon 라이브러리 : Java에서 JSON을 다루기 위한 라이브러리
// JackSon-databind : objectMapper를 이용해서 JSON형태로 넘어온 데이터를 특정 VO필드에 맞게 자동으로 매핑시켜줌
ObjectMapper objectMapper = new ObjectMapper();
ChatMessage chatMessage = objectMapper.readValue(message.getPayload(), ChatMessage.class); // 값의 타입은 ChatMessage.class
// 전달받은 메세지를 DB에 CHAT_MESSAGE테이블에 추가
int result = chatService.insertMessage(chatMessage);
// 메시지를 db에 성공적으로 저장했다면, 전달받은 메시지를 같은방에 접속중인 클라이언트들에게 전달
if(result > 0) {
for(WebSocketSession s : sessions) {
// 반복을 진행중인 WebSocketSession에 담겨있는 "방번호" 빼오기
// 채팅방에 입장을 할 때마다 방번호가 세션스코프에 저장이 될 것임.
// 세션안에 담겨있는 데이터는 handshake 덕분에 httpSession정보를 WebSocketSession에 넣을 것임.
int chatRoomNo = (int) s.getAttributes().get("chatRoomNo"); // 반환형이 Object여서 강제형변환
// chatRoomNo를 꺼내옴
// log.info("접속중인 사용자의 채팅방번호 : {}", chatRoomNo);
// 메시지에 담겨있는 채팅방 번호와, 현재 웹소켓세션에 저장된 채팅방번호를 비교하여 동일한 경우 해당 웹소켓세션에 메세지 전달
if(chatMessage.getChatRoomNo() == chatRoomNo) {
// chatMessage의 매개변수로 작성해서 보내야함. 이것도 JSON으로 변환해주는 작업필요 => Gson 이용
s.sendMessage(new TextMessage(new Gson().toJson(chatMessage)));
}
}
}
}
☞ 메시지에 담겨있는 채팅방 번호와, 현재 웹소켓세션에 저장된 채팅방번호를 비교하여 동일한 경우 해당 웹소켓세션에 메세지 전달
☞ chatMessage의 매개변수로 작성해서 보내야함. 이것도 JSON으로 변환해주는 작업필요 => Gson 이용
☞ 메이븐레파지토리 접속하여 Gson 코드 복사하여 pom.xml에 추가
▶ pom.xml
<!-- 챗웹소켓에서 필요한 Gson -->
<!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.10</version>
</dependency>
▶ chat.js
☞ 서버쪽 웹소켓핸들러에서 클라이언트소켓으로 메세지를 전달(sendMessage)하는 구문을 감지하는 이벤트 핸들러
=> ㅎㅎㅎ 라는 메세지를 보낸다고하면, 이런 데이터가 넘어가는 것을 볼 수 있다.
=> 전달된 메세지는 e.data내부에 (JSON)형태로 보관되어있다!
=> 전달받은 메세지를 JS객체로 변환할 예정
- 서버쪽 웹소켓핸들러에서 클라이언트소켓으로 메세지를 전달(sendMessage)하는 구문을 감지하는 이벤트 핸들러
// 서버쪽 웹소켓핸들러에서 클라이언트소켓으로 메세지를 전달(sendMessage)하는 구문을 감지하는 이벤트 핸들러
chattingSocket.onmessage = function(e){
console.log(e);
// 전달된 메세지는 e.data내부에 (JSON)형태로 보관되어있음
// 전달받은 메세지를 JS객체로 변환
const chatMessage = JSON.parse(e.data);
const li = document.createElement("li"); // <li>
const p = document.createElement("p"); // <p></p>
p.classList.add("chat");
// p태그 내부에 글내용추가 및 개행처리
p.innerHTML = chatMessage.message.replace(/\\n/gm, "<br>"); // <p class="chat">전달받은메세지</p>
const span = document.createElement("span");
span.classList.add("chatDate"); // <span class="chatDate">??</span>
span.innerText = currentTime(); // <span class="chatDate">2024-01-30</span>
// 내가 쓴 채팅인지, 상대방이 쓴 채팅인지 확인
if(chatMessage.userNo == userNo){
// 내가쓴글
li.classList.add("myChat"); // 내가쓴글에 해당하는 스타일 적용
li.append(span, p);
}else {
// 남이 쓴 글
li.innerHTML = `<b>${chatMessage.userName}</b>`;
li.append(p, span)
}
// 채팅창 요소가져오기
const display = document.querySelector(".display-chatting");
// 채팅창에 채팅내용 추가하기
display.append(li)
// 채팅창 맨 아래로 내리기
display.scrollTop = display.scrollHeight;
// scrollTop : 스크롤의 위치
// scrollHeight : 스크롤되는 요소(display)의 전체 높이
}
- 현재시간 출력 함수 ex) 2024-01-30
getFullYear: 2024 2025... 연도표시
// 현재시간 출력 함수 ex) 2024-01-30
// getFullYear: 2024 2025... 연도표시
function currentTime(){
const now = new Date();
return `${now.getFullYear()}-${now.getMonth()+1 < 10 ? "0"+ (now.getMonth() +1) : now.getMonth() +1}-${now.getDate() < 10 ? "0" +now.getDate() : now.getDate()}`;
}
- 페이지 로딩 완료후 => window.onload, 채팅창을 맨 아래로 내리는 작업
=> 즉시실행함수(IIFE, 속도 빠름, 변수명 중복문제도 해결)
=> () 괄호안에 익명함수를 넣어줌. 바로 실행해주기 위해서!
=> 뒤쪽에 함수호출 연산자를 넣음
=> 스크롤이 알아서 맨아래로 내려갈 것임!
(function(){
const display = document.querySelector(".display-chatting");
// 채팅창 맨 아래로 내리기
display.scrollTop = display.scrollHeight;
})();
▶ chat-mapper.xml
=> 날짜 형식대로 뽑혀서 출력하기 위해서 아래와 같이 수정.
▶ 결과
☞ 다른 브라우저창을 열어서 테스트를 해도 다른 사용자가 메시지를 보내면 바로 전달되는 것도 볼 수 있다!
☞ IP주소:80881/spring 하면 다른사람의 채팅방에도 접속가능하다!
'Server > Spring' 카테고리의 다른 글
[Spring] 11-1. 로그 처리 (0) | 2024.01.30 |
---|---|
[Spring] 10-5. 채팅방 나가기 (0) | 2024.01.30 |
[Spring] 10-3. 채팅방 통신(채팅방 메세지 추가) (0) | 2024.01.30 |
[Spring] 10-2. 채팅방 참여, 인원수 증가, 메세지 조회 (0) | 2024.01.29 |
[Spring] 10-1. 채팅방 목록, 채팅방 생성 (0) | 2024.01.29 |