깃허브:https://github.com/kimdhj/teamProject
오늘은 조금 오래 걸렸던 소캣 활용한 실시간 채팅을 설명해보겠습니다.
제가 했던 프로젝트 기반으로 하기 때문에 상단에 프로젝트 깃허브 주소 올려놓겠습니다.
시작은 여기있는 web.xml에서 부터 시작 됩니다.
여기서 소켓이라는 이름의 서블릿을 하나 만들어줍니다. 이 서블릿을 활용해서 소켓통신이 된다고 생각하시면 좋습니다.
그럼이에 따른 설정파일을 보겠습니다.
위에서 socket.xml이라고 선언했기 때문에 socket.xml 안에 설정을 해주어야합니다.
젤 마지막에 websocket 이부분이 젤 중요합니다 handler 부분은 오고가는 데이터를 어떻게 처리할건지 정해져있는 클래스를 가르키고 path는 저 경로로 오는것이 소켓에 관련된 것이다 라는 것입니다. sockjs는 sock종류 입니다.
spring은 sock.js사용합니다.
이것은 웹소켓 설정에 관한 부분입니다. 라이브러리 주소 핸들러이름 허용출처 등 여러가지 설정이 담겨있습니다.
package com.romance.socket;
import java.util.ArrayList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;
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;
@Component("echoHandler")
@RequestMapping("/echo")
public class EchoHandler extends TextWebSocketHandler {
@Autowired
chatServiceInter ser;
// 세션 리스트
private List<WebSocketSession> sessionList = new ArrayList<WebSocketSession>();
private static Logger logger = LoggerFactory.getLogger(EchoHandler.class);
// 클라이언트가 연결 되었을 때 실행
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
sessionList.add(session);
logger.info("{} 연결됨", session.getId());
}
// 클라이언트가 웹소켓 서버로 메시지를 전송했을 때 실행
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
System.out.println("{}로 부터 {} 받음"+ session.getId()+message.getPayload());
//받은메세지 데이터베이스에 등록(db)
chatVO vo=new chatVO();
vo.setReal_chat_session(session.getId());
String[] arr=message.getPayload().split(":");
vo.setRealchatname(arr[0]);
vo.setReal_chat_content(arr[1]);
System.out.println("실시간채팅 저장"+vo);
ser.insertchat(vo);
//모든 유저에게 메세지 출력
for(WebSocketSession sess : sessionList){
sess.sendMessage(new TextMessage(session.getId()+":"+message.getPayload()));
}
}
//클라이언트 연결을 끊었을 때 실행
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
sessionList.remove(session);
System.out.println("{} 연결 끊김."+ session.getId());
}
}
여기 핸들러가 있습니다
저같은경우 메세지를 받았을때 : 이거를 기준으로 작성자와 내용을 구분하기때문에 그에따라 데이터를 만들고 db에 저장하고 세션아이디를 붙여서 다시 전송해줍니다. 저기 for문에 의해서 모든 세션에 전달이 됩니다. 또한 생성되거나 끊겼을때 리스트에 넣고 빼고 해서 관리해주고 있습니다.
js부분에서는 이 부분이 젤 중요합니다 첫번재줄은 sock에 대한 설정입니다 자기에 맞는 주소를 괄호안에 넣어 주면 되고
두번재 줄은 메세지를 받았을때 실행할 함수를 넣어주고
세번재줄은 세션닫을때 실행할것
네번째줄은 세션을 처으만들었을때 실행할것을 적어주시면됩니다.
저같은 경우는 맨처음 db에서 저장된 채팅 내역을 가져오고 그이후에 onMessage에서 데이터를 받아서 이름부분이 자기거와 같거나 자기거+admin이면 출력하도록 설정했습니다.
개인적으로 소켓이란게 막 특별하기보다는 통신 경로를 하나 더 만들어서 거기서 통신을 하는거다 라고 생각하고 이해해서 더욱 빠르게 이해햇습니다.