BE/Spring Boot
[Spring Boot] STOMP란? / 간단한 채팅방 구현
셰욘
2025. 3. 18. 19:17
728x90
STOMP란?
Single (단순한) Text (텍스트 기반) Oriented Messaging Protocol (메시징 프로토콜)
웹 소켓과 함께 사용하는 메시징 프로토콜
기본적으로 웹 소켓은 양방향 통신을 가능하게 하지만,
메시지를 어떻게 주고받을지에 대한 형식을 정해주지 않는다.
-> STOMP를 사용하면 클라이언트와 서버 간 메시지 형식이 표준화되고,
채팅, 알림 시스템, 실시간 데이터 전송 등에 활용 가능
Pub-Sub 방식을 사용하여 한 명이 보낸 메시지를 여러 사람이 받을 수 있다. (대표적인 예로 채팅방이 있음)
STOMP 특징
텍스트 기반 프로토콜
- HTTP 처럼 간단한 프레임을 사용하여 메시지를 주고받음
Pub-Sub(발행-구독) 모델 지원
- 메시지를 특정 채널에 보내면, 해당 채널을 구독한 클라이언트들이 메시지를 받을 수 있음
브로커(Broker) 기반 통신
- 메시지를 직접 주고받는 게 아니라 브로커를 통해 전달
웹 소켓과 함께 사용 가능
- 웹 소켓을 기반으로 STOMP 메시지를 주고받을 수 있음
스프링 부트로 실시간 채팅방 구현
특정 채널을 구독한 클라이언트만 메시지를 받을 수 있게 구현
웹 소켓 라이브러리 추가
웹 소켓 기반으로 구현할 것이기 때문에 웹 소켓 라이브러리를 다운 받는다.
implementation 'org.springframework.boot:spring-boot-starter-websocket'
WebSocketConfig (웹 소켓 설정)
registry.enableSimpleBroker("/topic");
- 클라이언트가 메시지를 구독할 수 있는 prefix를 설정한다. (/topic/chat)
registry.setApplicationDestinationPrefixes("/app");
- 클라이언트가 메시지를 보낼 때 사용할 prefix를 설정한다. (/app/sendMessage)
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.enableSimpleBroker("/topic"); // 구독할 때 사용
registry.setApplicationDestinationPrefixes("/app"); // 메시지를 보낼 때 사용
}
// 모든 도메인에서 접속 가능하도록 설정
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/websocket")
.setAllowedOriginPatterns("*");
}
}
StompController
해당 주제를 구독하고 있는 사람한테만 메시지를 보낸다.
@RequiredArgsConstructor
@RestController
public class StompController {
private final SimpMessagingTemplate messagingTemplate;
@MessageMapping("/chat/{roomIdx}") // "/app/chat/5"로 메시지로 전송하면 실행되는 메소드
public void snedMessage (@DestinationVariable String roomIdx, String message) {
// 해당 주제를 구독하고 있는 사람한테만 메시지를 보냄
messagingTemplate.convertAndSend("/topic/room/" + roomIdx, message);
}
}
클라이언트 설정 (프론트엔드)
STOMP 설치
npm i @stomp/stompjs
Vue Router
path variable로 room idx를 넣어준다.
const routes = [
{ path: "/", component: Main },
{ path: "/stomp/:roomIdx", component: StompView },
];
View 파일
StompView.vue
<script setup>
import { Client } from "@stomp/stompjs";
import { onMounted, ref } from "vue";
import { useRoute } from "vue-router";
const route = useRoute();
const roomIdx = route.params.roomIdx;
const stompClient = ref(null);
const message = ref("");
// 메시지 보내기
const sendMessage = () => {
stompClient.value.publish({
destination: `/app/chat/${roomIdx}`,
body: message.value,
});
message.value = "";
};
onMounted(() => {
// stomp의 client 객체로 만들기
stompClient.value = new Client({
brokerURL: "ws://localhost:8080/ws",
connectHeaders: {},
// 연결 됐을 때 동작
onConnect: () => {
console.log("서버와 연결되었습니다.");
stompClient.value.subscribe(`/topic/room/${roomIdx}`, (message) => {
console.log(message.body + " 받았다.");
});
},
});
stompClient.value.activate();
});
</script>
<template>
<h1>stomp</h1>
<h3>채팅방 번호 : {{ roomIdx }}</h3>
<input v-model="message" type="text" placeholder="메세지를 입력하세요" />
<button @click="sendMessage">전송</button>
</template>
<style scoped></style>
테스트
다른 방 번호로 보냈을 때 메시지가 안 받아지는 걸 확인할 수 있다.
1번 방으로 'ㅎㅇ' 메시지를 보냈는데 2번 방에는 메시지 출력이 안
테스트는 간단한 채팅방 기능을 구현했지만,
메시지를 보내려는 사람이 방에 있는 사람인지 검증하는 과정이 필요하고
회원 정보 확인, 채팅방에 회원이 있는지 확인하는 등 추가적인 검증 과정이 필요하다.
728x90