HTTP 프로토콜과 호환되며, 실시간 양방향 통신을 제공하기 위한 프로토콜이며 Spring 4.0에서 등장한 네트워크 서비스이다. (접속까지는 HTTP프로토콜을 사용하지만 이후 WebSocket프로토콜로 변경)

WebSocket Config 작성하기
웹 소켓을 사용하기 위한 설정 파일이 필요하다.
+) @Configuration을 통해 해당 파일이 Bean 설정을 할 것을 나타냄
+) @EnableWebSocketMessageBroker을 통해 WebSocket사용을 나타냄
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer{
/*클라이언트가 웹 소켓 서버에 연결하는데 사용할 웹 소켓 엔드포인트 등록
withSockJS를 통해 웹 소켓을 지원하지 않는 브라우저에 대해 웹 소켓을 대체한다.
+)메소드명에 STOMP가 들어가는 경우 통신 프로토콜인 STOMP구현에서 작동된다. */
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/ws").withSockJS();
}
/*한 클라이언트에서 다른 클라이언트로 메시지를 라우팅하는데 사용될 메시지 브로커*/
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
//roomname으로 시작되는 요청을 구독한 모든 사용자들에게 메시지를 broadcast한다.
registry.enableSimpleBroker("/roomname");
// message로 시작되는 메시지는 message-handling methods로 라우팅된다.
registry.setApplicationDestinationPrefixes("/message");
}
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ChatMessageDTO {
private MessageType type;
private String content;
private String sender;
}
이때 MessageType은 일반 class가 아닌 enum으로 작성한다.
+) Java의 Enum타입은 일정 개수의 상수값을 선언하는 관련있는 상수들의 집합을 의미한다.
public enum MessageType {
CHAT,
JOIN,
LEAVE
}
@Controller
@Slf4j
public class ChatController {
@Autowired
private SimpMessageSendingOperations messagingTemplate;
ArrayList<String> users = new ArrayList<String>();
// 새로운 사용자가 웹 소켓을 연결할 때 실행됨
// @EventListener은 한개의 매개변수만 가질 수 있다.
@EventListener
public void handleWebSocketConnecListener(SessionConnectEvent event) {
log.info("Received a new web socket connection");
}
// 사용자가 웹 소켓 연결을 끊으면 실행됨
@EventListener
public void handleWebSocketDisconnectListener(SessionDisconnectEvent event) {
StompHeaderAccessor headerAccesor = StompHeaderAccessor.wrap(event.getMessage());
String username = (String) headerAccesor.getSessionAttributes().get("username");
if(username != null) {
log.info("User Disconnected : " + username);
users.remove(username);
System.out.println(users);
ChatMessageDTO chat = new ChatMessageDTO(MessageType.LEAVE, null, username);
messagingTemplate.convertAndSend("/roomname/public", chat);
}
}
// /message/sendMessage로 요청이 들어오면 해당 메소드로 처리된다.
@MessageMapping("/sendMessage")
@SendTo("/roomname/public")
public ChatMessageDTO sendMessage(@Payload ChatMessageDTO chat) {
return chat;
}
// /message/addUser로 요청이 들어오면 해당 메소드로 처리된다.
@MessageMapping("/addUser")
@SendTo("/roomname/public")
public ChatMessageDTO addUser(@Payload ChatMessageDTO chat, SimpMessageHeaderAccessor headerAccessor) {
headerAccessor.getSessionAttributes().put("username", chat.getSender());
users.add(chat.getSender());
return chat;
}
}