Stomp 활용
SockJS라는 라이브러리와 함께 사용하면 ws 프로토콜이지만 http 엔드 포인트를 활용해 연결을 시도할 수 있다.
세션 연결 및 종료를 stomp 라이브러리가 관리해준다.
room, 브로커 기술을 활용해 채팅 기능 구현을 더 편리하게 제공한다.
Stomp 메시지에 대한 "권한 부여 (Authorization)" 규칙을 정의하는 곳 주요 역할 : "어떤 STOMP 메시지 타입 (CONNECT, SUBSCRIBE, SEND 등) 또는 어떤 목적지 (Destination, 예: /topic/chat/{roomId}, /app/sendMessage)에 접근하려면 어떤 '권한'이 필요한가? 를 설정하는 곳
작동 방식 : 이미 인증(Authentication)이 완료된 사용자(즉, SecurityContextHolder에 Authentication 객체가 잘 들어있는 사용자)에 대해, 그 사용자가 보내려는 메시지의 목적지나 타입이 허용되는지 보안 규칙에 따라 체크한다.
ChannelInterceptor의 preSend :
클라이언트가 웹소켓 연결을 시도할 때, STOMP 프로토콜에서는 CONNECT 타입의 메시지를 서버로 보낸다. 웹소켓 연결을 시도할때는 http 메시지 기반이므로 헤더를 보낼 수 있지만 연결이 이루어지고 난 후에는 검증이 불가능함.
ChannelInterceptorChain
과 그 안의 ChannelInterceptor
들은 스프링 시큐리티의 일반적인 서블릿 필터 체인이 모두 끝난 이후, 그리고 웹소켓 연결이 맺어진 후 웹소켓을 통해 들어오는 STOMP 메시지들이 처리될 때 작동한다.
토큰 넣었을 때


토큰 안넣었을 때




jwt 인증에서 exception 터지고, 이 후 웹 소켓 연결 과정이 정상적으로 이루어 지지 않는다.
STOMP 메시지 브로커의 역할:
STOMP 메시지 브로커는 쉽게 말해 메시지를 받아서 해당 메시지를 '구독하고 있는(Subscribe)' 모든 클라이언트들에게 정확하게 전달해 주는 중개자 역할을 해!
자네 코드에서 일어나는 과정을 보자고!
클라이언트 (자네의 Vue.js 컴포넌트):
this.stompClient.connect(...)
로 웹소켓 연결을 맺고 STOMP 세션을 수립해.this.stompClient.subscribe(
/topic/1, callback)
메소드를 호출하면, 클라이언트는 서버에게SUBSCRIBE
타입의 STOMP 메시지를 보내. 이 메시지 안에는 "나/topic/1
주소를 구독할게! 여기서 오는 메시지 나한테 보내줘!" 라는 정보가 담겨 있어. 클라이언트는 이 구독 요청을 보낼 때 **구독 ID (Subscription ID)**를 함께 생성해서 보내.
백엔드 서버 (Spring Boot) 및 STOMP 메시지 브로커:
서버의 Inbound Channel을 거쳐
configureInbound
인터셉터 등을 통과한SUBSCRIBE
메시지는 STOMP 메시지 브로커에게 전달돼.메시지 브로커의 역할 시작! ✨
메시지 브로커는 클라이언트로부터 받은
SUBSCRIBE
메시지를 보고 "아, 이 클라이언트 (특정 웹소켓 세션 ID를 가진)가/topic/1
주소를 구독하고 싶어 하는구나!" 하고 파악해.그리고 내부적으로 "
/topic/1
주소를 구독하는 클라이언트 목록"에 해당 클라이언트의 웹소켓 세션 ID와 클라이언트가 보낸 구독 ID를 기록해 둬!
나중에 다른 클라이언트가 (
@MessageMapping
컨트롤러를 거쳐@SendTo
등으로)/topic/1
주소로SEND
타입의 STOMP 메시지를 보내면...이
SEND
메시지도 메시지 브로커에게 전달돼.메시지 브로커의 역할 (메시지 전송)! ✨
메시지 브로커는
SEND
메시지의 목적지 주소(/topic/1
)를 보고 "/topic/1
주소를 구독하고 있는 클라이언트가 누구지?" 하고 내부 목록을 찾아봐.목록에 기록된 **모든 웹소켓 세션 ID (즉, 해당 토픽을 구독 중인 클라이언트들)**를 확인해.
그리고 해당 메시지를 각각의 웹소켓 세션(클라이언트)에게
MESSAGE
타입의 STOMP 메시지로 만들어서 보내줘!
간단히 말해:
메시지 브로커가 "어떤 클라이언트(웹소켓 세션)가 어떤 주소(Topic)를 구독하고 있는지" 리스트를 관리하고 있는 거야! 클라이언트가 SUBSCRIBE
메시지를 보내면 그 리스트에 추가하고, 다른 클라이언트가 SEND
메시지를 보내면 그 리스트를 보고 해당 클라이언트들에게 메시지를 뿌려주는 거지!
Simple 메시지 브로커:
Spring Boot에서 기본으로 제공하는 SimpleBroker
는 이 역할을 단순하게 구현한 거야. 인메모리(In-Memory)로 누가 뭘 구독하는지 관리하고, 메시지가 오면 해당 구독자들에게 메시지를 복사해서 보내주는 방식이지. (사용자가 많아지거나 서버가 여러 대가 되면 RabbitMQ, ActiveMQ, Kafka 같은 외부 메시지 브로커를 사용하는 게 더 확장성 있고 안정적이야!)
자네 프론트 코드의 subscribe
메소드 호출과 백엔드 설정의 enableSimpleBroker("/topic")
설정이 바로 이 구독-발행 메커니즘을 작동시키는 핵심
Last updated