Spring WebSocket의 기본 개념과 클라이언트-서버 연결
WebSocket은 서버와 클라이언트 간의 양방향 실시간 통신을 가능하게 하는 기술이다.
이를 통해 클라이언트와 서버는 연결이 유지되는 동안 자유롭게 데이터를 주고받을 수 있다.
Spring에서는 @Configuration과 TextWebSocketHandler를 사용해 WebSocket 서버를 간편하게 구축할 수 있다.
이번 포스트에서는 Spring WebSocket의 주요 개념과 이를 통해 어떻게 클라이언트 연결을 관리하고 메시지를 전송하는지에 대해 다뤄본다.
1. WebSocketSession과 TextMessage
WebSocketSession
WebSocketSession은 WebSocket 연결을 추적하고 관리하는 핵심 객체이다.
클라이언트와 서버 간의 연결 상태를 추적하며, 클라이언트와의 연결이 끊어지면 해당 세션을 종료한다.
또한, 메시지를 클라이언트로 전송할 때 세션 객체를 통해 메시지를 보낼 수 있다.
WebSocketSession의 주요 역할은 다음과 같다:
- 연결 관리: 클라이언트와의 연결 상태를 추적하고, 연결된 클라이언트를 식별한다.
- 메시지 전송: 클라이언트와의 연결을 통해 메시지를 주고받을 수 있다.
- 세션 종료: 연결이 종료되면 세션을 관리하고 세션 목록에서 제거한다.
TextMessage
TextMessage는 WebSocket을 통해 텍스트 메시지를 주고받을 때 사용되는 객체이다.
메시지 본문을 String 형태로 저장하고 있으며, 클라이언트와 서버 간에 텍스트 메시지를 전송할 때 사용된다.
- 메시지 본문: 텍스트 메시지의 내용을 String 형식으로 저장한다.
- 메시지 전송: TextMessage 객체를 사용하여 텍스트 메시지를 서버에서 클라이언트로 전송하거나, 클라이언트에서 서버로 전송할 수 있다.
2. TextWebSocketHandler 사용
Spring에서는 TextWebSocketHandler를 확장하여 WebSocket 요청을 처리하는 핸들러를 구현한다.
이 핸들러는 클라이언트의 연결을 관리하고, 메시지를 처리하는 중요한 역할을 한다.
TextWebSocketHandler는 아래과 같은 메서드를 제공한다:
- afterConnectionEstablished(WebSocketSession session): 클라이언트가 서버에 연결되면 호출된다. 연결된 클라이언트의 세션을 저장하고, 클라이언트에게 환영 메시지를 전송할 수 있다.
- handleTextMessage(WebSocketSession session, TextMessage message): 클라이언트로부터 메시지를 받으면 호출된다. 받은 메시지를 다른 연결된 클라이언트들에게 전달하거나 필요한 처리를 할 수 있다.
- afterConnectionClosed(WebSocketSession session, CloseStatus status): 클라이언트의 연결이 종료되면 호출된다. 연결된 세션을 목록에서 제거하는 등의 처리를 한다.
심플하게 정리된 각 메서드의 용도:
- afterConnectionEstablished: 연결 수립 시 호출
- handleTextMessage: 텍스트 메시지 수신 시 호출
- afterConnectionClosed: 연결 종료 시 호출
예시 코드: 기본적인 WebSocket 핸들러 구현
package com.example.websocket.handler;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;
import org.springframework.web.socket.TextMessage;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
public class ChatHandler extends TextWebSocketHandler {
// 연결된 클라이언트를 저장하는 Set
private static final Set<WebSocketSession> sessions = Collections.synchronizedSet(new HashSet<>());
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
// 클라이언트가 연결되면 세션을 추가
sessions.add(session);
session.sendMessage(new TextMessage("채팅 서버에 연결되었습니다."));
}
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
// 클라이언트로부터 메시지가 수신되면 모든 연결된 세션에 메시지를 전송
for (WebSocketSession s : sessions) {
s.sendMessage(new TextMessage(message.getPayload()));
}
}
@Override
public void afterConnectionClosed(WebSocketSession session, org.springframework.web.socket.CloseStatus status) throws Exception {
// 클라이언트 연결이 종료되면 세션에서 제거
sessions.remove(session);
}
}
코드 설명
- sessions: WebSocketSession 객체를 저장하는 Set이다. 연결된 모든 클라이언트의 세션을 저장하여, 연결된 모든 클라이언트에게 메시지를 전송할 수 있게 한다.
- afterConnectionEstablished: 클라이언트가 서버와 연결되었을 때 호출된다. 이 메서드는 클라이언트의 세션을 sessions 리스트에 추가하고, 클라이언트에게 연결 성공 메시지를 보낸다.
- handleTextMessage: 클라이언트가 서버에 메시지를 보낼 때 호출된다. 이 메서드는 받은 메시지를 연결된 모든 클라이언트에게 전달한다.
- afterConnectionClosed: 클라이언트의 연결이 종료되면 호출된다. 연결이 종료된 클라이언트의 세션을 sessions에서 제거한다.
3. 클라이언트 연결 종료 후 세션 제거
클라이언트의 연결이 종료되면 afterConnectionClosed 메서드가 호출되어 해당 WebSocketSession을 세션 목록에서 제거한다.
클라이언트가 브라우저를 닫거나 연결을 종료하면 서버는 더 이상 해당 클라이언트에 메시지를 보낼 필요가 없으므로 세션을 제거해야 한다. 이를 통해 불필요한 메모리 누수를 방지하고, 효율적인 서버 리소스 관리를 할 수 있다.
4. Spring WebSocket 의존성
Spring WebSocket을 사용하려면 spring-boot-starter-websocket 의존성을 추가해야 한다.
이 의존성을 추가하면 TextWebSocketHandler, WebSocketSession, TextMessage 등을 비롯한 WebSocket 관련 클래스를 사용할 수 있다.
Gradle 의존성
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-websocket'
}
총 정리
- Spring WebSocket은 실시간 채팅이나 알림 시스템을 구축하는 데 유용한 기술이다.
- TextWebSocketHandler를 사용하면 WebSocket 연결을 손쉽게 관리하고, 클라이언트와 서버 간의 양방향 실시간 메시지 전송을 구현할 수 있다.
- 이 기술을 통해 서버는 여러 클라이언트와 실시간으로 데이터를 주고받을 수 있으며, 클라이언트가 연결을 종료하면 서버는 해당 세션을 관리하여 리소스를 효율적으로 처리할 수 있다.
'JAVA > Spring' 카테고리의 다른 글
Jackson과 Lombok @Data 어노테이션을 이용한 JSON 데이터 처리 (0) | 2024.12.31 |
---|---|
Java에서 ProcessBuilder와 클래스패스 설정에 대한 이해 (0) | 2024.12.30 |
Spring 의존성 주입: 생성자 주입과 수정자 주입의 동작 원리 (1) | 2024.12.21 |
Spring @ComponentScan의 includeFilters와 excludeFilters 완벽 이해 (0) | 2024.12.21 |
Spring의 ComponentScan 이해하기: @ComponentScan의 동작 원리와 활용법 (1) | 2024.12.21 |
댓글