<aside> 💡 이 글에서는 스프링을 이용해 저장된 채팅 내용을 불러오고 WebSocket으로 실시간 채팅을 구현한다.
</aside>
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic");
config.setApplicationDestinationPrefixes("/app");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/chat-websocket").withSockJS();
}
}
@Data
@Entity
public class ChatMessage {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String content;
private LocalDateTime timestamp;
}
@Controller
public class ChatController {
private final ChatMessageRepository chatMessageRepository;
@Autowired
public ChatController(ChatMessageRepository chatMessageRepository) {
this.chatMessageRepository = chatMessageRepository;
}
@GetMapping("/chat")
public String getChatPage(Model model) {
List<ChatMessage> messages = chatMessageRepository.findAll();
model.addAttribute("messages", messages);
return "chat";
}
@MessageMapping("/chat.sendMessage")
@SendTo("/topic/publicChatRoom")
public ChatMessage sendMessage(ChatMessage chatMessage) {
chatMessageRepository.save(chatMessage);
return chatMessage;
}
@MessageMapping("/chat.addUser")
@SendTo("/topic/publicChatRoom")
public ChatMessage addUser(ChatMessage chatMessage) {
chatMessageRepository.save(chatMessage);
return chatMessage;
}
@MessageMapping("/chat.getChatHistory")
@SendTo("/topic/publicChatRoom")
public List<ChatMessage> getChatHistory() {
// 이전 채팅 내용
return chatMessageRepository.findAll();
}
}
public interface ChatMessageRepository extends JpaRepository<ChatMessage, Long> {}
<!DOCTYPE html>
<html xmlns:th="<http://www.thymeleaf.org>">
<head>
<title>채팅</title>
<script src="/webjars/sockjs-client/sockjs.min.js"></script>
<script src="/webjars/stomp-websocket/stomp.min.js"></script>
<script>
let stompClient = null;
const connect = () => {
const socket = new SockJS('/chat-websocket');
stompClient = Stomp.over(socket);
stompClient.connect({}, (frame) => {
stompClient.subscribe('/topic/publicChatRoom', (chatMessage) => {
showMessage(JSON.parse(chatMessage.body));
});
// 채팅방에 입장할 때 이전 채팅 내용 가져오기
stompClient.send("/app/chat.getChatHistory", {}, '');
});
};
const disconnect = () => {
if (stompClient !== null) {
stompClient.disconnect();
}
};
const sendMessage = () => {
const content = document.getElementById('messageInput').value;
const chatMessage = {
content: content
};
stompClient.send("/app/chat.sendMessage", {}, chatMessage);
document.getElementById('messageInput').value = '';
};
const showMessage = (chatMessage) => {
const messageElement = document.createElement('li');
messageElement.innerHTML = chatMessage.content;
document.getElementById('chatMessages').appendChild(messageElement);
};
window.onload = connect;
window.onunload = disconnect;
</script>
</head>
<body onload="connect()" onunload="disconnect()">
<h1>Chat</h1>
<ul id="chatMessages">
<li th:each="message : ${messages}" th:text="${message.content}"></li>
</ul>
<form>
<input type="text" id="messageInput" required/>
<button type="button" onclick="sendMessage()">전송</button>
</form>
</body>
</html>