해당 글에서는 Spring Boot 기반 WebSocket에 대해 이해하고 초기 설정 이후 WebScocket에 연결하는 방법에 대해 알아봅니다
1) Spring Boot WebSocket
💡 Spring Boot WebSocket
- Spring Framework에서 제공하는 기능으로, 실시간 양방향 통신을 가능하게 해 줍니다. Web Socket을 사용하면 서버와 클라이언트 간의 연결이 지속적으로 유지되어, 데이터를 실시간으로 주고받을 수 있습니다.
- 이는 채팅 애플리케이션, 실시간 알림 시스템, 주식 거래 플랫폼 등에서 유용하게 사용됩니다.

💡 [참고] 소켓 통신에 대해 궁금하시면 아래의 글을 참고하시면 도움이 됩니다.
[데이터 통신] 소켓 통신(Socket Communication) 이해하기 : 송신-수신 통신 과정
해당 글에서는 소켓 통신의 흐름의 이해를 돕기 위해 작성한 글입니다.1) 소켓 통신(Socket Communication)💡 소켓 통신(Socket Communication)- 네트워크에서 두 컴퓨터 간의 ‘실시간 양방향 통신’을 제공
adjh54.tistory.com
1. STOMP(Simple or Streaming Text Oriented Messaging Protocol)
💡 STOMP(Simple or Streaming Text Oriented Messaging Protocol)
- 텍스트 기반의 메시징 프로토콜을 의미합니다. 클라이언트와 메시지 브로커 간의 통신을 간단하고 효율적으로 수행할 수 있도록 설계되었습니다. 이는 WebScoket에서 쉽게 메시지를 주고받을 때 사용이 됩니다.
- 해당 프로토콜은 Websocket을 사용하여 클라이언트와 서버 간의 메시지 교환을 구조화하고 표준화하는 데 사용됩니다.
명령어 | 설명 |
CONNECT | 클라이언트가 서버에 연결을 요청할 때 사용합니다. |
SEND | 클라이언트 또는 서버가 특정 목적지로 메시지를 보낼 때 사용합니다. |
SUBSCRIBE | 클라이언트가 특정 목적지의 메시지를 구독할 때 사용합니다. |
UNSUBSCRIBE | 클라이언트가 특정 목적지의 메시지 구독을 취소할 때 사용합니다. |
DISCONNECT | 클라이언트가 서버와의 연결을 종료할 때 사용합니다. |
Getting Started | Using WebSocket to build an interactive web application
In Spring’s approach to working with STOMP messaging, STOMP messages can be routed to @Controller classes. For example, the GreetingController (from src/main/java/com/example/messagingstompwebsocket/GreetingController.java) is mapped to handle messages t
spring.io
💡 [참고] WebSocket 내에서 Java에서의 Stomp도 있지만, Node 기반의 Socket.io도 존재합니다. 이에 대해 궁금하시면 아래의 글을 참고하시면 도움이 됩니다.
[Node] Socket.io 기반 소켓 서버 구축 방법 -1 : 구성 요소 및 흐름 + React 기반 채팅 화면 구성
해당 글에서는 소켓 통신을 위해 Socket.io를 기반으로 소켓 서버를 구현하고, 채팅을 하는 예시를 구축해 봅니다. 💡 [참고] 아래의 Socket.io와 관련된 글들을 참고하시면 도움이 됩니다분류링크S
adjh54.tistory.com
2) Spring Boot WebSocket 구성요소
1. WebSocketConfigurer 인터페이스
💡WebSocketConfigurer 인터페이스
- Spring Framework에서 WebSocket 구성을 위한 인터페이스입니다. 이 인터페이스를 구현하면 WebSocket 엔드포인트와 핸들러를 등록할 수 있습니다.
- 즉, 해당 엔드포인트는 클라이언트가 '웹 소켓을 연결'하기 위한 엔드포인트 입니다. Spring Boot Server가 로컬에서 실행하고 8080 포트인 경우 http://localhost:8080/[엔드포인트]로 접근을 합니다.
기능 | 설명 |
WebSocket 엔드포인트 등록 | registerWebSocketHandlers() 메서드를 통해 WebSocket 엔드포인트를 등록할 수 있습니다. |
핸들러 매핑 | 특정 URL 패턴에 WebSocketHandler를 매핑할 수 있습니다. |
CORS 설정 | WebSocket 연결에 대한 CORS(Cross-Origin Resource Sharing) 설정을 할 수 있습니다. |
SockJS 지원 | SockJS 폴백 옵션을 활성화하여 WebSocket을 지원하지 않는 브라우저에 대한 대체 솔루션을 제공할 수 있습니다. |
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(new MyWebSocketHandler(), "/myHandler")
.setAllowedOrigins("*")
.withSockJS();
}
}
WebSocketConfigurer (Spring Framework 6.1.13 API)
docs.spring.io
💡 [참고] WebSocketHandlerRegistry의 주요 메서드
메서드 | 설명 |
addHandler(WebSocketHandler handler, String... paths) | WebSocket 핸들러를 지정된 URL 경로에 등록합니다. |
setAllowedOrigins(String... origins) | 허용된 오리진(도메인)을 설정합니다. CORS(Cross-Origin Resource Sharing) 정책을 관리하는 데 사용됩니다. |
withSockJS() | SockJS 폴백 옵션을 활성화합니다. WebSocket을 지원하지 않는 브라우저에 대한 대체 솔루션을 제공합니다. |
setOrder(int order) | 핸들러의 우선순위를 설정합니다. 낮은 값일수록 높은 우선순위를 가집니다. |
addInterceptors(HandshakeInterceptor... interceptors) | WebSocket 핸들셰이크 과정에 인터셉터를 추가합니다. |
setHandshakeHandler(HandshakeHandler handshakeHandler) | 사용자 정의 핸드셰이크 핸들러를 설정합니다. |
WebSocketHandlerRegistration (Spring Framework 6.1.13 API)
Add more handlers that will share the same configuration (interceptors, SockJS config, etc).
docs.spring.io
2. TextWebSocketHandler 클래스
💡 TextWebSocketHandler
- Spring Framework에서 제공하는 WebSocket 핸들러 클래스입니다. 이 클래스는 '텍스트 기반의 WebSocket 메시지를 처리'하는 데 특화되어 있습니다.
특징 | 설명 |
텍스트 메시지 처리 | 문자열 형태의 WebSocket 메시지를 쉽게 처리할 수 있습니다. |
추상 클래스 | TextWebSocketHandler는 추상 클래스로, 개발자가 필요한 메서드를 오버라이드하여 사용합니다. |
WebSocketHandler 인터페이스 구현 | WebSocketHandler인터페이스를 구현하여 WebSocket의 기본적인 생명주기 메서드를 제공합니다. |
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;
public class MyWebSocketHandler extends TextWebSocketHandler {
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
String payload = message.getPayload();
// 메시지 처리 로직
session.sendMessage(new TextMessage("서버에서 보내는 응답: " + payload));
}
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
// 연결 설정 후 로직
}
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
// 연결 종료 후 로직
}
}
💡 [참고] TextWebSocketHandler와 같이 텍스트 처리외에 다른 웹 소켓 처리방식들
클래스 | 설명 |
AbstractWebSocketHandler | 빈 메서드로 구현된 WebSocketHandler의 편리한 기본 클래스입니다. |
BinaryWebSocketHandler | 바이너리 메시지만 처리하는WebSocketHandler구현을 위한 편리한 기본 클래스입니다. |
PerConnectionWebSocketHandler | 각 WebSocket 연결에 대해 WebSocketHandler인스턴스를 초기화하고 소멸시키며 다른 모든 메서드를 위임하는 WebSocketHandler입니다. |
TextWebSocketHandler | 텍스트 메시지만 처리하는 WebSocketHandler구현을 위한 편리한 기본 클래스입니다. |
3. WebSocketMessageBrokerConfigurer 인터페이스
💡 WebSocketMessageBrokerConfigurer
- Spring Framework에서 WebSocket 및 STOMP 메시징을 구성하는 데 사용되는 인터페이스입니다. 이 인터페이스를 구현하면 WebSocket 통신을 위한 다양한 설정을 할 수 있습니다.
- @EnableWebSocketMessageBroker 어노테이션을 통해서 WebSocket 메시징을 활성화하는 메서드입니다.
- 이를 사용하여 STOMP 프로토콜을 통한 WebSocket 메시지를 주고받을 수 있도록 메시징을 구성할 수 있습니다.
기능 | 설명 |
메시지 브로커 구성 | 클라이언트와 서버 간의 메시지 라우팅을 관리합니다. |
WebSocket 엔드포인트 등록 | 클라이언트가 연결할 수 있는 WebSocket 엔드포인트를 정의합니다. |
메시지 핸들러 설정 | 들어오는 메시지를 처리할 핸들러를 구성합니다. |
@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("/ws").withSockJS();
}
}
💡 [참고] WebSocketMessageBrokerConfigurer 클래스의 주요 메서드
메서드 | 반환 타입 | 설명 |
addArgumentResolvers | void | 커스텀 컨트롤러 메서드 인자 타입을 지원하기 위한 리졸버를 추가합니다. |
addReturnValueHandlers | void | 커스텀 컨트롤러 메서드 반환 값 타입을 지원하기 위한 핸들러를 추가합니다. |
configureClientInboundChannel | void | WebSocket 클라이언트로부터 들어오는 메시지를 위한 MessageChannel을 구성합니다. |
configureClientOutboundChannel | void | WebSocket 클라이언트로 나가는 메시지를 위한 MessageChannel을 구성합니다. |
configureMessageBroker | void | 메시지 브로커 옵션을 구성합니다. |
configureMessageConverters | boolean | 주석이 달린 메서드의 메시지 페이로드 추출 및 메시지 전송 시 사용할 메시지 변환기를 구성합니다. |
configureWebSocketTransport | void | WebSocket 클라이언트로부터 받은 메시지와 클라이언트로 보내는 메시지 처리와 관련된 옵션을 구성합니다. |
getPhase | Integer | SmartLifecycle 타입의 WebSocket 메시지 처리 빈이 실행되어야 하는 단계를 반환합니다. |
registerStompEndpoints | void | 각각 특정 URL에 매핑되는 STOMP 엔드포인트를 등록하고, 선택적으로 SockJS 폴백 옵션을 활성화하고 구성합니다. |
3) 개발 환경 구축 및 웹 소켓 구축
1. 구성 환경
💡 구성 환경
- 해당 글은 아래의 환경하에 WebScocket 구성이 되어 있습니다.
구성 | 환경 버전 |
Java | 17 |
spring-boot | 3.3.2 |
spring-boot-starter-websocket | 3.3.2 |
Lombok | - |
2. 라이브러리 추가
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-websocket:3.3.2'
}
Maven Repository: org.springframework.boot » spring-boot-starter-websocket » 3.3.2
💡 [참고] 아래와 같은 패키지 구조로 구성을 하였습니다.

3. Chrome 확장 프로그램 : Web Socket Client
💡Chrome 확장 프로그램 : Web Socket Client
- Chorme 브라우저에서 WebSocket 연결을 위한 확장 프로그램을 설치합니다.
- 이를 사용하는 이유는 Websocket 연결에 대한 테스트와 간단한 데이터를 주고받는 환경을 테스트를 수행하기 위해 사용됩니다.

Web Socket Client - Chrome 웹 스토어
A tool for manual web socket testing.
chromewebstore.google.com
4. WebSocketConfig 클래스 구성
💡 WebSocketConfig 클래스 구성
- WebSocket 최초 연결을 위해 구성하는 환경 구성 파일 클래스입니다.
1. @EnableWebSocket
- WebSocket 사용을 활성화하고 @Configuration 어노테이션을 통해 환경파일임을 지정합니다.
- 이 어노테이션을 사용하면 Spring 애플리케이션에서 WebSocket 기능을 사용할 수 있습니다.
2. WebSocketConfigurer(interface)
- WebSocketConfigurer 인터페이스로부터 구현체 registerWebSocketHandlers 메서드를 구성합니다.
- 이 인터페이스를 구현하면 registerWebSocketHandlers 메서드를 통해 WebSocket 핸들러를 등록할 수 있습니다.
3. registerWebSocketHandlers()
- WebSocketConfigurer 인터페이스로부터 오버라이딩 받은 WebSocket 핸들러를 구성합니다.
- 클라이언트에서 /ws-stomp 경로로 WebSocket 연결을 시도하면 ChatWebSocketHandler으로 연결을 처리하게 핸들러를 등록합니다.
package com.adjh.springbootwebsocket.config;
import com.adjh.springbootwebsocket.config.handler.ChatWebSocketHandler;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
/**
* Spring Framework에서 WebSocket 구성을 위한 클래스입니다.
*
* @author : jonghoon
* @fileName : WebSocketConfig
* @since : 8/15/24
*/
@Configuration
@EnableWebSocket
@RequiredArgsConstructor
public class WebSocketConfig implements WebSocketConfigurer {
private final ChatWebSocketHandler chatWebSocketHandler;
/**
* WebSocket 연결을 위해서 Handler를 구성합니다.
*
* @param registry
*/
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
System.out.println("[+] 최초 WebSocket 연결을 위한 등록 Handler");
registry
// 클라이언트에서 웹 소켓 연결을 위해 "ws-stomp"라는 엔드포인트로 연결을 시도하면 ChatWebSocketHandler 클래스에서 이를 처리합니다.
.addHandler(chatWebSocketHandler, "ws-stomp")
// 접속 시도하는 모든 도메인 또는 IP에서 WebSocket 연결을 허용합니다.
.setAllowedOrigins("*");
}
}
5. ChatWebSocketHandler 클래스 구성
💡 ChatWebSocketHandler 클래스 구성
- WebSocket 연결 이후 연결을 처리하는 핸들러를 의미합니다.
- TextWebSocketHandler를 상속받아서 최초 소켓 세션을 연결하고 소켓/전송 오류가 발생했을 때 및 ‘텍스트 기반 메시지’를 보내거나 받을 수 있도록 처리를 가능하게 합니다.
1. afterConnectionEstablished() : 연결 성공
- WebSocket 협상이 성공적으로 완료되고 WebSocket 연결이 열려 사용할 준비가 된 후 호출됩니다. 성공을 하였을 경우 session 값을 추가합니다.
2. handleTextMessage() : 메시지 전달
- 새로운 WebSocket 메시지가 도착했을 때 호출됩니다.전달 받은 메시지를 순회하면서 메시지를 전송합니다.
- message.getPayload()를 통해 메시지가 전달이 됩니다.
3. afterConnectionClosed() : 소켓 종료 및 전송 오류
- WebSocket 연결이 어느 쪽에서든 종료되거나 전송 오류가 발생한 후 호출됩니다.
- 종료 및 실패하였을 경우 해당 세션을 제거합니다.
package com.adjh.springbootwebsocket.config.handler;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
/**
* 텍스트 기반의 WebSocket 메시지를 처리를 수행하는 Handler 입니다.
*
* @author : jonghoon
* @fileName : ChatWebSocketHandler
* @since : 8/15/24
*/
@Component
public class ChatWebSocketHandler extends TextWebSocketHandler {
// WebSocket Session들을 관리하는 리스트입니다.
private static final ConcurrentHashMap<String, WebSocketSession> clientSession = new ConcurrentHashMap<>();
/**
* [연결 성공] WebSocket 협상이 성공적으로 완료되고 WebSocket 연결이 열려 사용할 준비가 된 후 호출됩니다.
* - 성공을 하였을 경우 session 값을 추가합니다.
*
* @param session
* @throws Exception
*/
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
System.out.println("[+] afterConnectionEstablished :: " + session.getId());
clientSession.put(session.getId(), session);
}
/**
* [메시지 전달] 새로운 WebSocket 메시지가 도착했을 때 호출됩니다.
* - 전달 받은 메시지를 순회하면서 메시지를 전송합니다.
* - message.getPayload()를 통해 메시지가 전달이 됩니다.
*
* @param session
* @param message
* @throws Exception
*/
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
System.out.println("[+] handleTextMessage :: " + session);
System.out.println("[+] handleTextMessage :: " + message.getPayload());
clientSession.forEach((key, value) -> {
System.out.println("key :: " + key + " value :: " + value);
if (!key.equals(session.getId())) { //같은 아이디가 아니면 메시지를 전달합니다.
try {
value.sendMessage(message);
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
/**
* [소켓 종료 및 전송 오류] WebSocket 연결이 어느 쪽에서든 종료되거나 전송 오류가 발생한 후 호출됩니다.
* - 종료 및 실패하였을 경우 해당 세션을 제거합니다.
*
* @param session
* @param status
* @throws Exception
*/
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws IOException {
clientSession.remove(session);
System.out.println("[+] afterConnectionClosed - Session: " + session.getId() + ", CloseStatus: " + status);
}
}
💡 [참고] TextWebSocketHandler 인터페이스 메서드
메서드 | 리턴 타입 | 설명 |
afterConnectionEstablished(WebSocketSession session) | void | WebSocket 협상이 성공적으로 완료되고 WebSocket 연결이 열려 사용할 준비가 된 후 호출됩니다. |
afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) | void | WebSocket 연결이 어느 쪽에서든 종료되거나 전송 오류가 발생한 후 호출됩니다. |
handleMessage(WebSocketSession session, WebSocketMessage<?> message) | void | 새로운 WebSocket 메시지가 도착했을 때 호출됩니다. |
handleTransportError(WebSocketSession session, Throwable exception) | void | 기본 WebSocket 메시지 전송 중 오류가 발생했을 때 처리합니다. |
supportsPartialMessages() | boolean | WebSocketHandler가 부분 메시지를 처리하는지 여부를 반환합니다. |
WebSocketHandler (Spring Framework 6.1.13 API)
Invoked after the WebSocket connection has been closed by either side, or after a transport error has occurred.
docs.spring.io
6. WebSocketStompBrokerConfig
💡 WebSocketStompBrokerConfig
- WebSocket 및 STOMP 메시징 처리를 구현하는 WebSocketMessageBrokerConfigurer 인터페이스의 구현체입니다.
- 이를 통해 WebSocket 통신을 위한 다양한 설정을 구성할 수 있습니다.
1. @EnableWebSocketMessageBroker
- WebSocket 메시지 브로커를 활성화합니다. 이 애노테이션을 사용하면, 해당 클래스는 WebSocket 메시징을 위한 설정을 할 수 있습니다.
2. WebSocketMessageBrokerConfigurer
- WebSocket 연결을 처리하는 핸들러를 의미합니다. TextWebSocketHandler를 상속하여 ‘텍스트 기반 메시지’를 보내거나 받을 수 있도록 처리가 가능합니다.
3. configureMessageBroker(MessageBrokerRegistry config)
- 메시지 브로커를 구성하는 메서드로, 메시지 브로커가 특정 목적지로 메시지를 라우팅 하는 방식을 설정합니다.
- enableSimpleBroker() 메서드를 통해 접두사를 지정하여 클라이언트가 접두사로 시작하는 주제를 “구독(Sub)”하여 메시지를 받을 수 있습니다.
- setApplicationDestinationPrefixes() 메서드를 통해 접두사로 시작하는 클라이언트가 서버로 메시지를 “발행(Sub)” 이 접두사를 사용합니다.
4. registerStompEndpoints()
- STOMP(WebSocket 메시지 브로커 프로토콜) 엔드포인트를 등록하는 메서드로, 클라이언트가 WebSocket에 연결할 수 있는 엔드포인트를 정의합니다.
- addEndpoint() : 클라이언트가 WebSocket에 연결하기 위한 엔드포인트를 "/ws-stomp"로 설정합니다.
- setAllowedOrigins() : 클라이언트의 origin을 명시적으로 지정합니다.
- withSockJS() :WebSocket을 지원하지 않는 브라우저에서도 SockJS를 통해 WebSocket 기능을 사용할 수 있게 합니다.
package com.adjh.springbootwebsocket.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
/**
* STOMP를 사용하여 메시지 브로커를 설정합니다
* WebSocket 메시지 브로커의 설정을 정의하는 메서드들을 제공합니다. 이를 통해 메시지 브로커를 구성하고 STOMP 엔드포인트를 등록할 수 있습니다.
*
* @author : jonghoon
* @fileName : WebSocketStompBrokerConfig
* @since : 8/15/24
*/
@Configuration // 설정 클래스로 지정합니다.
@EnableWebSocketMessageBroker // WebSocket 메시지 브로커를 활성화합니다.
public class WebSocketStompBrokerConfig implements WebSocketMessageBrokerConfigurer {
/**
* configureMessageBroker() : 메시지 브로커 옵션을 구성합니다.
*
* @param config
*/
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
// 구독(sub) : 접두사로 시작하는 메시지를 브로커가 처리하도록 설정합니다. 클라이언트는 이 접두사로 시작하는 주제를 구독하여 메시지를 받을 수 있습니다.
// 예를 들어, 소켓 통신에서 사용자가 특정 메시지를 받기위해 "/sub"이라는 prefix 기반 메시지 수신을 위해 Subscribe합니다.
config.enableSimpleBroker("/sub");
// 발행(pub) : 접두사로 시작하는 메시지는 @MessageMapping이 달린 메서드로 라우팅됩니다. 클라이언트가 서버로 메시지를 보낼 때 이 접두사를 사용합니다.
// 예를 들어, 소켓 통신에서 사용자가 특정 메시지를 전송하기 위해 "/pub"라는 prefix 기반 메시지 전송을 위해 Publish 합니다.
config.setApplicationDestinationPrefixes("/pub");
}
/**
* registerStompEndpoints() : 각각 특정 URL에 매핑되는 STOMP 엔드포인트를 등록하고, 선택적으로 SockJS 폴백 옵션을 활성화하고 구성합니다.
*
* @param registry
*/
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
/*
* addEndpoint : 클라이언트가 WebSocket에 연결하기 위한 엔드포인트를 "/ws-stomp"로 설정합니다.
* withSockJS : WebSocket을 지원하지 않는 브라우저에서도 SockJS를 통해 WebSocket 기능을 사용할 수 있게 합니다.
*/
registry
// 클라이언트가 WebSocket에 연결하기 위한 엔드포인트를 "/ws-stomp"로 설정합니다.
.addEndpoint("/ws-stomp")
// 클라이언트의 origin을 명시적으로 지정
.setAllowedOrigins("<http://localhost:3000>")
// WebSocket을 지원하지 않는 브라우저에서도 SockJS를 통해 WebSocket 기능을 사용할 수 있게 합니다.
.withSockJS();
}
}
[ 더 알아보기 ]
💡 WebSocketConfig에서 지정한 엔드포인트와 WebSocketStompBrokerConfig에서 지정한 엔드포인트는 무슨 차이가 있는가?
1. WebSocketConfig 엔드포인트
- 기본적인 WebSocket 연결을 위한 것입니다. 이는 클라이언트가 최초로 WebSocket 연결을 설정할 때 사용하는 URL입니다.
2. WebSocketStompBrokerConfig 엔드포인트
- STOMP 프로토콜을 사용하는 WebSocket 연결을 위한 것입니다. 이 엔드포인트는 STOMP 클라이언트가 서버와 STOMP 세션을 설정하기 위해 사용합니다.
💡 그럼 최초 연결을 위해서는 WebSocketConfig 엔드포인트를 이용하고, 구독/발행을 할 때는 WebSocketStompBrokerConfig의 엔드포인트를 이용하는 게 맞는 걸까?
- 맞습니다. 최초 WebSocket 연결을 위해서는 WebSocketConfig 엔드포인트를 이용하고, 구독/발행 시에는 WebSocketStompBrokerConfig에서 정의한 엔드포인트와 정의한 접두사 (/sub, /pub)을 사용합니다.
7. ChatMessageDto
💡 ChatMessageDto
- 클라이언트와 데이터를 주고 받기 위해 구성한 DTO입니다.
- 지역 변수로 content 값을 통해 메시지를 구성하며, sender를 통해서 보내는 주체를 지정하였습니다.
package com.adjh.springbootwebsocket.dto;
import lombok.Data;
/**
* 구독자와 수신자 간의 메시지를 주고받는 형태를 구성한 Object입니다.
*
* @author : jonghoon
* @fileName : ChatMessage
* @since : 8/16/24
*/
@Data
public class ChatMessageDto {
private String content;
private String sender;
public ChatMessageDto(String content, String sender) {
this.content = content;
this.sender = sender;
}
}
8. ChatController
💡 ChatController
- 해당 Controller에서는 STOMP를 사용하여 메시지를 처리하는 컨트롤러입니다.
- @MessageMapping를 통해서 메시지로 특정 경로로 들어오는 메시지를 처리합니다.
구분 | 설명 | 엔드포인트 |
발행자(Publisher) | 메시지를 전송하는 역할을 수행합니다 | /pub/messages |
구독자(Subscriber) | 메시지를 수신하는 역할을 수행합니다 | /sub/message |
package com.adjh.springbootwebsocket.controller;
import com.adjh.springbootwebsocket.dto.ChatMessageDto;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
/**
* WebSocket 데이터를 처리를 수행한 Controller입니다.
*
* @author : jonghoon
* @fileName : ChatController
* @since : 8/15/24
*/
@RestController
public class ChatController {
private final SimpMessagingTemplate template; // 특정 사용자에게 메시지를 보내는데 사용되는 STOMP을 이용한 템플릿입니다.
@Autowired
public ChatController(SimpMessagingTemplate template) {
this.template = template;
}
/**
* Message 엔드포인트로 데이터와 함께 호출을 하면 "/sub/message"를 수신하는 사용자에게 메시지를 전달합니다.
*
* @param chatMessageDto
* @return
*/
@MessageMapping("/messages")
public ChatMessageDto send2(@RequestBody ChatMessageDto chatMessageDto) {
template.convertAndSend("/sub/message", chatMessageDto.getContent()); // 구독중인 모든 사용자에게 메시지를 전달합니다.
return chatMessageDto;
}
}
4) 결과 확인 : 소켓 서버 연결(Chrome Extension)
1. 소켓 서버 연결
💡 소켓 서버 연결
- 지정한 Endpoint로 접속하여 소켓 서버의 연결을 확인하였습니다.
- 해당 코드에서는 ws://localhost:8081/ws-stomp로 연결을 수행하였습니다.

2. 소켓 서버 간 통신
💡 소켓 서버 간 통신
- 해당 Google Extenstion 내에서는 Message Text라는 기능이 있어서, 두 개의 브라우저 간에서 각각 세션아이디가 다르기에 다른 세션 간의 메시지가 서로 통신이 됨을 확인하였습니다.

3. 소켓 서버 내 콘솔 확인
💡 소켓 서버 내 콘솔 확인
- 소켓 서버 내에서 ChatWebSocketHandler 클래스 내에 구현한 handleTextMessage() 메서드의 작성해 둔 콘솔 메시지를 통해서 아래와 같이 출력이 잘됨을 확인하였습니다.

4. 구성한 React 앱 내에서 직접 메시지를 전송합니다.
💡 구성한 React 앱 내에서 직접 메시지를 전송합니다.
- 위에서 구성한 웹 소켓 서버는 아래의 엔드포인트로 호출을 통해 데이터를 실시간으로 주고받을 수 있습니다.
구분 | 엔드포인트 | 설명 |
소켓 서버 연결 | http://localhost:8081/ws-stomp | 소켓 서버에 연결을 하는데 사용이 되는 엔드포인트 입니다. |
메시지 전송 | /pub/messages | 메시지는 전송하기 위해 사용되는 엔드포인트입니다. |
메시지 수신 | /sub/message | 메시지를 수신하기 위해 사용되는 엔드포인트입니다. |

💡 [참고] 해당 구성 내용은 아래의 Repository 내에서 확인이 가능합니다.
blog-codes/spring-boot-websocket at main · adjh54ir/blog-codes
Contributor9 티스토리 블로그 내에서 활용한 내용들을 담은 레포지토리입니다. Contribute to adjh54ir/blog-codes development by creating an account on GitHub.
github.com
blog-codes/react-chatting at main · adjh54ir/blog-codes
Contributor9 티스토리 블로그 내에서 활용한 내용들을 담은 레포지토리입니다. Contribute to adjh54ir/blog-codes development by creating an account on GitHub.
github.com
💡 [참고] 해당 구성한 WebSocket 서버의 클라이언트를 구성에 대해 궁금하시면 아래의 글을 참고하시면 도움이 됩니다.
[React] STOMP 기반 소켓 서버 활용하기 : @stomp/stompjs, sockjs-client
해당 글에서는 WebSocket 서버와의 연결을 통해서 STOMP Client를 이용하여 실시간 웹 소켓 통신을 구현하는 방법에 대해 알아봅니다 💡 [참고] STOMP을 이용한 웹 소켓 및 Socket.io를 이용한 소켓 연결
adjh54.tistory.com
오늘도 감사합니다. 😀