Spring Boot와 WebSockets를 사용한 실시간 채팅 애플리케이션 만들기
Overview
실시간 채팅 애플리케이션은 사용자 간의 즉각적인 소통을 가능하게 하는 중요한 애플리케이션입니다. Spring Boot와 WebSockets를 사용하여 이런 애플리케이션을 만드는 방법을 단계별로 설명하겠습니다. WebSockets는 클라이언트와 서버 간의 양방향 통신을 가능하게 하여, 실시간 데이터 전송에 매우 적합합니다. 이 가이드는 Spring Boot를 활용하여 기본적인 실시간 채팅 기능을 구현하는 방법을 상세히 다룹니다.
1. 프로젝트 설정
1.1. Spring Boot 프로젝트 생성
먼저, Spring Boot 프로젝트를 생성합니다. Spring Initializr를 사용하면 손쉽게 시작할 수 있습니다.
- Spring Initializr 웹사이트를 방문합니다.
- 다음과 같은 설정을 합니다:
- Project: Maven Project
- Language: Java
- Spring Boot: 최신 안정 버전
- Group: com.example
- Artifact: chat-app
- Dependencies: Web, WebSocket
- "Generate" 버튼을 클릭하여 프로젝트를 다운로드하고, IDE에서 엽니다.
1.2. WebSocket 의존성 추가
pom.xml
파일에 WebSocket 관련 의존성을 추가합니다. Spring Boot는 기본적으로 WebSocket 지원을 제공하지만, 추가로 spring-boot-starter-websocket
을 명시적으로 추가할 수 있습니다.
<dependencies>
<!-- Other dependencies -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
</dependencies>
2. WebSocket 설정
2.1. WebSocket 설정 클래스
WebSocket을 설정하기 위해 WebSocketConfig
클래스를 생성합니다. 이 클래스는 WebSocket의 엔드포인트와 핸들러를 설정합니다.
package com.example.chatapp.config;
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;
import com.example.chatapp.handler.ChatHandler;
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(new ChatHandler(), "/chat").setAllowedOrigins("*");
}
}
2.2. WebSocket 핸들러
WebSocket 핸들러는 클라이언트의 메시지를 처리하는 역할을 합니다. ChatHandler
클래스를 만들어 WebSocket 메시지를 수신하고 브로드캐스트합니다.
package com.example.chatapp.handler;
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.Collections;
import java.util.HashSet;
import java.util.Set;
public class ChatHandler extends TextWebSocketHandler {
private final Set<WebSocketSession> sessions = Collections.synchronizedSet(new HashSet<>());
@Override
public void afterConnectionEstablished(WebSocketSession session) throws IOException {
sessions.add(session);
}
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws IOException {
for (WebSocketSession sess : sessions) {
if (sess.isOpen() && !sess.getId().equals(session.getId())) {
sess.sendMessage(message);
}
}
}
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) {
sessions.remove(session);
}
}
3. 클라이언트 구현
3.1. HTML과 JavaScript
클라이언트 측에서는 HTML과 JavaScript를 사용하여 WebSocket과 연결하고 메시지를 송수신합니다. index.html
파일을 src/main/resources/static
폴더에 생성합니다.
<!DOCTYPE html>
<html>
<head>
<title>Chat Application</title>
<style>
#chatBox {
width: 100%;
height: 300px;
border: 1px solid #ccc;
overflow-y: scroll;
}
#messageInput {
width: 80%;
}
</style>
</head>
<body>
<h1>Chat Application</h1>
<div id="chatBox"></div>
<input id="messageInput" type="text" placeholder="Type your message here...">
<button onclick="sendMessage()">Send</button>
<script>
var socket = new WebSocket("ws://localhost:8080/chat");
socket.onmessage = function(event) {
var chatBox = document.getElementById('chatBox');
chatBox.innerHTML += '<div>' + event.data + '</div>';
chatBox.scrollTop = chatBox.scrollHeight;
};
function sendMessage() {
var messageInput = document.getElementById('messageInput');
var message = messageInput.value;
socket.send(message);
messageInput.value = '';
}
</script>
</body>
</html>
4. 애플리케이션 실행 및 테스트
4.1. 애플리케이션 실행
프로젝트의 루트 디렉토리에서 다음 명령어를 실행하여 애플리케이션을 시작합니다:
mvn spring-boot:run
4.2. 테스트
브라우저에서 http://localhost:8080
으로 접속하여 채팅 애플리케이션이 정상적으로 동작하는지 확인합니다. 여러 브라우저를 열어 메시지를 주고받으며 실시간 채팅 기능을 테스트합니다.
5. 문제 해결 및 에러 처리
5.1. CORS 에러
웹 브라우저에서 CORS 정책으로 인해 연결이 거부될 수 있습니다. WebSocket 설정에서 setAllowedOrigins("*")
를 사용하여 모든 출처에서의 연결을 허용합니다. 실제 배포 환경에서는 신뢰할 수 있는 출처만 허용하는 것이 좋습니다.
5.2. 서버에서 메시지 전송 오류
메시지를 서버에서 전송할 때 IOException
이 발생할 수 있습니다. 이러한 오류는 클라이언트와 서버 간의 연결 문제로 인해 발생할 수 있으며, WebSocket 핸들러의 handleTextMessage
메소드에서 적절한 예외 처리를 통해 대응할 수 있습니다.
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) {
for (WebSocketSession sess : sessions) {
if (sess.isOpen() && !sess.getId().equals(session.getId())) {
try {
sess.sendMessage(message);
} catch (IOException e) {
// 로그를 남기거나 에러 처리를 합니다.
}
}
}
}
참고문서
이 문서들을 통해 WebSocket의 작동 원리와 Spring Boot에서의 활용 방법에 대해 더 깊이 이해할 수 있습니다.
'Study Information Technology' 카테고리의 다른 글
Spring Boot와 WebSocket 실시간 웹 애플리케이션 구현하기 (0) | 2024.08.20 |
---|---|
ROS 메시지와 서비스 설계 및 사용 (0) | 2024.08.20 |
Python의 multiprocessing 모듈로 병렬 처리하기 (0) | 2024.08.20 |
Spring Boot에서 JSON 직렬화 이해하기 (0) | 2024.08.20 |
Spring Boot와 Hazelcast를 이용한 분산 캐시 구현 (0) | 2024.08.20 |