1. WebSocket 소개
WebSocket 프로토콜 (RFC 6455)
- 클라이언트와 서버 간에 하나의 TCP 연결 위에서 양방향(full-duplex) 통신 가능.
- HTTP를 기반으로 동작하지만, HTTP와는 다른 프로토콜이다.
- 80, 443 포트 사용
- 기존 방화벽 규칙 재사용 가능.
참고사항
- WebSocket 서버가 nginx 같은 프록시 서버 뒤에 있을 경우, 업그레이드 요청을 프록시가 제대로 전달하도록 설정 필요.
- 클라우드 환경에서는 WebSocket 지원 여부를 클라우드 제공업체 문서에서 확인해야 함.
2. WebSocket API
설정
- WebSocketConfigurer 오버라이딩
예제
더보기
@Configuration
public class WebsocketConfig implements WebSocketConfigurer {
@Autowired
private ChatMessageHandler chatMessageHandler;
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(chatMessageHandler, "/chat");
}
}
전체 흐름
[Client]
↓ (HTTP Upgrade 요청: ws://)
[HandshakeInterceptor] <-- (Spring에서는 HandlerInterceptor 계열로 등록하는 HandshakeInterceptor)
↓
[DefaultHandshakeHandler] <-- (handshake를 처리하고 실제 WebSocket 연결을 만듬)
↓
[WebSocketHandlerDecorator] <-- (연결 이후부터 통신을 감싸서 부가기능 추가)
↓
[실제 WebSocketHandler] <-- (너가 작성하는 실제 비즈니스 처리)
단계 | 설명 |
HandshakeInterceptor (HandlerInterceptor 계열) |
WebSocket 연결 핸드쉐이크 전 작업 등록 (토큰 인증, 세션 체크, 요청 헤더 검사) - WebSocket 업그레이드 요청 전에 HTTP 요청을 가로챔 |
DefaultHandshakeHandler |
WebSocket 프로토콜로 업그레이드를 실제로 수행
- RequestUpgradeStrategy: WAS마다 WebSocket을 어떻게 업그레이드 할지를 정하는 전략 - 클라이언트 세션 ID 부여 |
WebSocketHandlerDecorator | 연결이 완료된 이후 통신 과정을 감싸면서 부가기능 추가 (로깅, 에러처리, 커스텀 로직 등) - ExceptionWebSocketHandlerDecorator: 에러 처리 (WebSocket 에러 시, 1011로 연결 종료) |
WebSocketHandler |
WebSocket 연결 이후, 수신 프레임을 처리하는 핸들러
- 프레임 유형에 맞게 상속해서 구현하는 방식 (TextWebSocketHandler, BinaryWebSocketHandler) |
예제) HandshakeInterceptor
더보기
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(chatMessageHandler, "/chat")
.addInterceptors(new HttpSessionHandshakeInterceptor()); // HTTP attribute를 Websocket 세션에 전달하는 목적으로 사용됨
}
예제) DefaultHandshakeHandler
더보기
@Bean
public DefaultHandshakeHandler handshakeHandler() {
// Tomcat을 위한 RequestUpgradeStrategy 설정
RequestUpgradeStrategy strategy = new TomcatRequestUpgradeStrategy();
return new DefaultHandshakeHandler(strategy);
}
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(myHandler(), "/ws")
.setHandshakeHandler(handshakeHandler()); // 여기 연결
}
예제) WebSocketHandlerDecorator
더보기
public class LoggingWebSocketHandlerDecorator extends WebSocketHandlerDecorator {
public LoggingWebSocketHandlerDecorator(WebSocketHandler delegate) {
super(delegate);
}
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
System.out.println("WebSocket 연결 완료: " + session.getId());
super.afterConnectionEstablished(session);
}
@Override
public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
System.out.println("WebSocket 에러 발생: " + exception.getMessage());
super.handleTransportError(session, exception);
}
}
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(new LoggingWebSocketHandlerDecorator(chatMessageHandler), "/chat")
}
예제) WebSocketHandler
더보기
@Component
public class ChatMessageHandler extends TextWebSocketHandler {
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
System.out.println("chat message received");
System.out.println("payload: " + message.getPayload());
}
}
3. 부가 기능
배포
- Jakarta WebSocket (JSR-356)은 기본적으로 클래스패스 스캔 또는 초기화 API 등록 방식으로 WebSocket 엔드포인트를 배포.
- DispatcherServlet처럼 모든 HTTP를 하나로 통합할 수 없음 (인터셉터, URL 패턴 등)
- Spring은 이를 해결하기 위해 WAS별 RequestUpgradeStrategy를 제공
Jakarta WebSocket (@ServerEndpoint)
|
Spring MVC (@RestController)
|
|
요청 수신 | 서버(WAS)가 직접 받음 |
DispatcherServlet이 다 받음
|
등록 방식 | 어노테이션 스캔 or 직접 등록 |
빈 등록 + RequestMapping
|
확장성 | 제한적 (필터 체인 끼우기 어렵다) |
매우 유연 (필터/인터셉터 쉽게 추가)
|
에러 처리 | 엔드포인트 단위 |
전역 예외처리(ControllerAdvice 등) 가능
|
라이프사이클 | WAS 관리 |
Spring 컨테이너 관리
|
Cross-Oriign 허용
예제
더보기
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(chatMessageHandler, "/chat")
.addInterceptors(new HttpSessionHandshakeInterceptor())
.setAllowedOrigins("*");
}
옵션
- 메시지 버퍼 크기, idle timeout 등 조정 가능
예제
더보기
@Bean
public ServletServerContainerFactoryBean servletServerContainerFactoryBean() {
ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean();
container.setMaxTextMessageBufferSize(1024 * 8);
container.setMaxBinaryMessageBufferSize(1024 * 8);
container.setMaxSessionIdleTimeout((1000L * 60 * 10));
return container;
}
출처
'Spring > Spring' 카테고리의 다른 글
[Spring WebSockets] 2-3. STOMP: 부가 기능 (1) | 2025.05.04 |
---|---|
[Spring WebSockets] 2-1. STOMP: 주요 내용 (0) | 2025.05.03 |
[Spring][AOP] 3. Advisor API (0) | 2025.04.09 |
[Spring][AOP] 2. Pointcut API (1) | 2025.04.09 |
[Spring][AOP] 1. Advice API (0) | 2025.04.09 |