728x90
1.WebSocket 의존성 추가
Spring Boot 프로젝트에서 WebSocket 기능을 사용하기 위해 필요한 의존성을 추가해준다.
<!-- Spring Boot WebSocket -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
2.WebSocketConfig
WebSocket 메시지 브로커를 활성화한다.
STOMP를 기반으로 한 메시징 기능을 활성화하여 클라이언트-서버 간 실시간 통신을 가능하게한다.
@Configuration
@EnableWebSocketMessageBroker // 웹소켓 메시지 브로커 활성화
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
2-1.configureMessageBroker
메시지 브로커를 활성화하며, 클라이언트가 구독할 수 있는 경로를 설정한다.
클라이언트가 /topic/ㅁㅁ을 구독하면 서버가 이 경로로 메시지를 보낼 수있고 클라이언트가 /app/sendMessage로 메시지를 보내면, 서버의 컨트롤러에서 @MessageMapping("/sendMessage")로 처리된다.
// 클라이언트가 구독할 prefix 설정 (메시지 브로커가 처리)
// 클라이언트가 메세지를 보낼 때 사용할 prefix
@Override
public void configureMessageBroker(@NonNull MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic");
config.setApplicationDestinationPrefixes("/app");
}
2-1-1.enableSimpleBroker
메시지 브로커가 처리할 수 있는 prefix로 topic을 지정하였고 그 안의 세부 채널이름은 개발자가 지정한다.
만약 /topic/public을 구독하면 @SendTo("/topic/public")을 통해 브로드캐스트 가능하다.
config.enableSimpleBroker("/topic");
2-1-2.setApplicationDestinationPrefixes
다음 코드는 클라이언트가 /app/xxx 형태로 메시지를 보내면, Spring은 해당 메시지를 @MessageMapping("xxx")이 붙은 메서드로 라우팅하게된다.
config.setApplicationDestinationPrefixes("/app");
2-2.registerStompEndpoints
클라이언트가 STOMP 프로토콜로 WebSocket 연결을 시도할 때 접속할 경로로 ws를 설정하였고 CORS처리를 해줬다.
@Override
public void registerStompEndpoints(@NonNull StompEndpointRegistry registry) {
registry.addEndpoint("/ws")
.setAllowedOrigins("http://localhost:5173", "http://localhost:8080", "http://127.0.0.1:3000")
.withSockJS();
}
추후 브라우저는 /ws 경로를 통해 HTTP 핸드셰이크 요청을 보내게 된다.
const socket = new SockJS("http://localhost:8080/ws");
3.ChatMessage DTO
ChatMessage를 위한 DTO다
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class ChatMessage {
private MessageType type;
private String content;
private String sender;
public enum MessageType {
CHAT,
JOIN,
LEAVE
}
}
4.ChatController
@Controller
public class ChatController {
@MessageMapping("/chat.sendMessage") // 클라이언트가 "/app/chat.sendMessage"로 보낸 메시지를 처리
@SendTo("/topic/public") // 구독한 클라이언트들에게 전달
public ChatMessage sendMessage(@Payload ChatMessage chatMessage) {
return chatMessage; // 그대로 브로드캐스트
}
}
4-1.@MessageMapping("/chat.sendMessage")
클라이언트가 STOMP 메시지를 서버로 보낼 때 사용하는 경로이다.
클라이언트가 /app/chat.sendMessage로 메시지를 보내면 실행된다는 뜻이다.
다음은 프론트엔드 코드
stompClient.send("/app/chat.sendMessage", {}, JSON.stringify({
type: "CHAT",
sender: "사용자1",
content: message
}));
4-2.@SendTo("/topic/public")
이 메서드의 반환값은 구독 중인 모든 클라이언트에게 브로드캐스트된다는 의미다.
4-3.@Payload ChatMessage chatMessage
STOMP 메시지의 본문(payload)을 ChatMessage 객체로 자동 매핑해준다.
5.프론트엔드 코드
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>WebSocket 채팅 테스트</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/sockjs-client/1.6.1/sockjs.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/stomp.js/2.3.3/stomp.min.js"></script>
</head>
<body>
<h2>WebSocket 채팅 테스트</h2>
<div>
<input type="text" id="message" placeholder="메시지를 입력하세요" />
<button onclick="sendMessage()">전송</button>
</div>
<div id="chat"></div>
<script>
const socket = new SockJS("http://localhost:8080/ws");
const stompClient = Stomp.over(socket);
stompClient.connect({}, () => {
console.log("WebSocket 연결됨");
stompClient.subscribe("/topic/public", (message) => {
const chatBox = document.getElementById("chat");
const msg = JSON.parse(message.body);
// 변수 치환을 위해 역슬래시를 제거합니다.
chatBox.innerHTML += `<p><strong>${msg.sender}:</strong> ${msg.content}</p>`;
});
});
function sendMessage() {
const messageInput = document.getElementById("message");
const message = messageInput.value;
if (message.trim() !== "") {
stompClient.send("/app/chat.sendMessage", {}, JSON.stringify({
type: "CHAT",
sender: "사용자1",
content: message
}));
messageInput.value = "";
}
}
</script>
</body>
</html>
728x90
'BackEnd > SpringBoot' 카테고리의 다른 글
[SpringBoot] JWT + Oauth2 추가하기 (0) | 2025.04.07 |
---|---|
[SpringBoot] Actuator + Prometheus + Grafana 로 모니터링 (0) | 2025.03.24 |
[SpringBoot] log aspect, API 표준 Response 제작 (0) | 2025.03.23 |