개인프로젝트로 호두스케쥴러를 개발하는 중에 수업에서 배웠던 스프링 웹소켓(spring-websocke)을 이용한 챗봇/실시간 채팅방을 구현해보았다.
사실 웹소켓에 대해서는 대강 코드들만 이해한 수준이라 완벽하게 내 것으로 만들지 못했다. 본 포스팅은 이를 복기하며 추후 다시 공부하기 위해 남겨보는 것이다.
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-messaging</artifactId>
<version>${org.springframework-version}</version>
</dependency>
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;
import com.multi.hodooScheduler.common.interceptor.HttpHandsShakeInterceptor;
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
//채팅방 이름 설정
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/task");
config.setApplicationDestinationPrefixes("/app");
}
//채팅 내용을 보낼 주소(endPoint == url)
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
//chat: 실시간 채팅용
registry.addEndpoint("/chat"); //자바 소켓 통신 가능
registry.addEndpoint("/chat").withSockJS(); //자바 스크립트 소켓 통신
//chat2: 챗봇용
registry.addEndpoint("/chat2").setAllowedOrigins("*").addInterceptors(new HttpHandsShakeInterceptor()).withSockJS(); //자바 소켓 통신 가능
// 로그인 유무 확인과 로그인한 유저의 정보를 얻어보기 위해 인터셉터 추가
/*
* registry.addEndpoint("/chat2").setAllowedOrigins("*").withSockJS(); //자바 스크립트
* 소켓 통신
*/ }
}

import java.util.Map;
import javax.servlet.http.HttpSession;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.HandshakeInterceptor;
public class HttpHandsShakeInterceptor implements HandshakeInterceptor {
@Override
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
Map<String, Object> attributes) throws Exception {
if(request instanceof ServletServerHttpRequest) {
ServletServerHttpRequest servletResquest = (ServletServerHttpRequest) request;
HttpSession session = servletResquest.getServletRequest().getSession();
attributes.put("session", session); // 로그인 유저의 정보가 담긴 httpsession을 websocketsession에 session이란 이름으로 추가해준다.
}
return true;
}
@Override
public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
Exception exception) {
// TODO Auto-generated method stub
}
}
@Controller
public class WebSocketController {
private TaskService taskService;
private DiaryService diaryService;
@Autowired
public WebSocketController(TaskService taskService, DiaryService diaryService) {
super();
this.taskService = taskService;
this.diaryService = diaryService;
}
@MessageMapping("/chat2") // 채팅 내용 받을 때 사용하는 주소
@SendTo("/task/messages2")
public OutputMessage2 send2(Message message, SimpMessageHeaderAccessor messageHeaderAccessor) { // from: guest,
// text:1
System.out.println("받은 데이터>>" + message);
HttpSession session = (HttpSession) messageHeaderAccessor.getSessionAttributes().get("session");
// 인터셉터에서 추가한 session을 가져온다.
UserDTO loginUser = (UserDTO) session.getAttribute("loginUser");
System.out.println(loginUser);
OutputMessage2 out = new OutputMessage2();
String menu = "";
switch (message.getText()) {
case "1":
if (loginUser == null) {
menu = "로그인이 필요합니다. 로그인을 해주세요.";
} else {
try {
ArrayList<TaskDTO> list = taskService.selectTaskList(loginUser);
for (TaskDTO t : list) {
menu += t.getContent() + ": " + (t.getComplete().equals("N") ? "미완, " : "완료, ");
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
menu = "오류발생";
}
}
break;
case "2":
if (loginUser == null) {
menu = "로그인이 필요합니다. 로그인을 해주세요.";
} else {
try {
PageDTO pageDTO = new PageDTO();
pageDTO.setUserId(loginUser.getUserId());
pageDTO.setPage(1);
pageDTO.setStartEnd(1);
ArrayList<DiaryDTO> list = diaryService.diaryList(pageDTO);
for (DiaryDTO d : list) {
menu += "( " + d.getCreatedDate() + " ) 제목: " + d.getTitle() + ", ";
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
menu = "오류발생";
}
}
break;
default:
menu = "챗 봇>>선택한 번호는 없는 메뉴입니다. 다시 입력해주세요.";
break;
}
System.out.println("메뉴는" + menu);
out.setMenu(menu);
return out;
}
@MessageMapping("/chat") // 채팅 내용 받을 때 사용하는 주소
@SendTo("/task/messages") // 가입주소한 브라우저에 return message를 json으로 변환해서 보내줌.
public OutputMessage send(Message message) {
System.out.println("받은 데이터>>" + message);
OutputMessage out = new OutputMessage();
out.setFrom(message.getFrom());
out.setText(message.getText());
Date date = new Date();
out.setTime(date.getHours() + ":" + date.getMinutes());
return out;
}
}


본 포스팅은 멀티캠퍼스의 멀티잇 백엔드 개발(Java)의 교육을 수강하고 작성되었습니다.