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