728x90
개요
Spring Boot와 WebSocket을 활용하면 효율적인 실시간 통신 기능을 구현할 수 있다.
이번 글에서는 Redis를 추가로 사용해 메시지 저장과 자동 삭제 기능을 갖춘 채팅 시스템을 구축하는 방법을 작성했다.
구성요소
- WebSocket: 클라이언트와 서버 간의 양방향 통신을 가능하게 하는 프로토콜.
- Redis: 메시지 저장소로 활용하며 TTL(Time to Live)을 사용해 일정 시간이 지나면 메시지를 삭제.
- Spring Boot: WebSocket 서버를 구현하는 데 사용.
WebSocket 설정
Spring Boot에서 WebSocket 서버를 구현하려면 @EnableWebSocket과 WebSocketHandler를 사용한다.
WebSocketConfig.java
WebSocket 설정파일
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;
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
private final ChatHandler chatHandler;
public WebSocketConfig(ChatHandler chatHandler) {
this.chatHandler = chatHandler;
}
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(chatHandler, "/ws/chat").setAllowedOrigins("*");
}
}
ChatHandler.java
메시지를 처리하는 핵심 클래스
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;
public class ChatHandler extends TextWebSocketHandler {
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
String payload = message.getPayload();
System.out.println("Received: " + payload);
session.sendMessage(new TextMessage("Echo: " + payload));
}
}
Redis 설정
Redis는 메시지를 저장하고 TTL을 활용해 자동 삭제 기능을 제공한다.
RedisConfig.java
Redis 설정파일
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory);
return template;
}
}
ChatMessageService.java
Redis에 메시지를 저장하면서 TTL을 설정한다.
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import java.util.concurrent.TimeUnit;
@Service
public class ChatMessageService {
private final RedisTemplate<String, String> redisTemplate;
public ChatMessageService(RedisTemplate<String, String> redisTemplate) {
this.redisTemplate = redisTemplate;
}
public void saveMessage(String roomId, String message) {
String key = "chat:" + roomId;
redisTemplate.opsForList().leftPush(key, message);
redisTemplate.expire(key, 1, TimeUnit.HOURS); // 1시간 후 자동 삭제
}
public List<String> getMessages(String roomId) {
String key = "chat:" + roomId;
return redisTemplate.opsForList().range(key, 0, -1);
}
}
WebSocket과 Redis 연결
WebSocket에서 받은 메시지를 Redis에 저장한다.
ChatHandler.java
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;
public class ChatHandler extends TextWebSocketHandler {
private final ChatMessageService chatMessageService;
public ChatHandler(ChatMessageService chatMessageService) {
this.chatMessageService = chatMessageService;
}
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
String payload = message.getPayload();
System.out.println("Received: " + payload);
// 메시지 저장
String roomId = "room1"; // 예제에서는 고정된 채팅방 ID 사용
chatMessageService.saveMessage(roomId, payload);
// 클라이언트에 응답
session.sendMessage(new TextMessage("Saved: " + payload));
}
}
Frontend WebSocket 연결
클라이언트에서 WebSocket을 통해 서버와 연결한다.
const socket = new WebSocket("ws://localhost:8080/ws/chat");
socket.onopen = () => {
console.log("WebSocket connection established.");
socket.send("Hello, server!");
};
socket.onmessage = (event) => {
console.log("Message from server:", event.data);
};
문의사항이나 피드백은 댓글로 남겨주세요.
'프로그래밍 언어 > JAVA, SPRING' 카테고리의 다른 글
[SPRING BATCH] 1. 스프링 배치란 (0) | 2024.12.04 |
---|---|
[SPRING BOOT] 멀티모듈 프로젝트 설계하기 (1) | 2024.11.26 |
[SPRING BOOT] CORS 에러와 DELETE요청 해결하기 (0) | 2024.11.26 |
[SPRING BOOT] UnrecognizedPropertyException 해결하기 (0) | 2024.11.26 |
[JAVA] Exception Handling (0) | 2024.07.22 |