728x90
소켓이란?
소켓(Socket)은 네트워크 상에서 서로 다른 프로그램이 데이터를 송수신하기 위한 종단점입니다.
소켓은 IP 주소와 포트 번호를 기반으로 통신하며, 클라이언트와 서버 간의 연결을 유지하거나 메시지를 교환하는 데 사용됩니다.
소켓의 주요 개념
- IP 주소: 네트워크 상에서 컴퓨터를 식별하는 고유 주소.
- 포트 번호: 특정 애플리케이션(프로세스)을 식별하는 번호.
- 소켓 연결: 클라이언트와 서버가 데이터를 주고받기 위해 소켓을 통해 이루어지는 연결.
웹소켓(WebSocket)이란?
기존 HTTP 프로토콜은 요청-응답 기반으로 작동하여 실시간 양방향 통신이 어렵습니다.
웹소켓(WebSocket)은 이러한 한계를 극복하기 위해 만들어진 프로토콜로,
- 서버와 클라이언트 간에 지속적인 연결을 유지하며,
- 실시간으로 양방향 데이터를 주고받을 수 있도록 지원합니다.
웹소켓의 특징
- 양방향 통신: 서버와 클라이언트가 서로 데이터를 주고받을 수 있음.
- 연결 지속성: 연결이 유지되는 동안 추가적인 핸드셰이크 없이 데이터 교환.
- 효율성: 요청 없이 서버가 데이터를 푸시(Push) 가능.
스프링에서 웹소켓 구현하기
스프링 프레임워크는 STOMP 프로토콜을 사용하여 간단하게 웹소켓 기반의 실시간 통신을 구현할 수 있습니다.
아래는 스프링을 활용한 실시간 채팅 애플리케이션 예제입니다.
1. 프로젝트 설정
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-websocket'
}
2. 웹소켓 설정
WebSocketConfig 클래스에서 웹소켓 엔드포인트와 메시지 브로커를 설정합니다.
@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") // WebSocket 엔드포인트
.setAllowedOriginPatterns("*") // CORS 설정
.withSockJS(); // SockJS 지원
}
}
3. 채팅 컨트롤러
클라이언트의 메시지를 처리하고, 구독자에게 메시지를 전달합니다.
@Controller
public class ChatController {
@MessageMapping("/chat/{roomName}") // 클라이언트 메시지 처리
@SendTo("/topic/{roomName}") // 구독 경로로 메시지 전송
public String sendMessage(String message) {
return message;
}
}
4. HTML 클라이언트 예제
채팅방에 연결하고 메시지를 주고받는 클라이언트 코드입니다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Chat Rooms</title>
<script src="https://cdn.jsdelivr.net/npm/sockjs-client/dist/sockjs.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/stompjs/lib/stomp.min.js"></script>
<style>
body {
font-family: Arial, sans-serif;
}
.container {
width: 50%;
margin: auto;
padding: 20px;
text-align: center;
}
input, button {
margin: 5px;
}
.messages {
border: 1px solid #ccc;
padding: 10px;
margin-top: 10px;
height: 200px;
overflow-y: auto;
}
</style>
</head>
<body>
<div class="container">
<h1>Chat Rooms</h1>
<input id="roomInput" type="text" placeholder="Enter room name" />
<button onclick="joinRoom()">Join Room</button>
<br>
<input id="messageInput" type="text" placeholder="Enter your message" />
<button onclick="sendMessage()">Send</button>
<div class="messages" id="messages"></div>
</div>
<script>
let stompClient = null; // STOMP 클라이언트 객체를 저장할 변수
let currentRoom = null; // 현재 사용자가 접속한 채팅방 이름을 저장할 변수
// 서버와 WebSocket 연결을 설정하는 함수
function connect() {
// 1. '/ws' 엔드포인트에 SockJS를 사용하여 WebSocket 연결 생성
const socket = new SockJS('/ws');
// 2. SockJS 객체를 사용하여 STOMP 클라이언트 생성
stompClient = Stomp.over(socket);
// 3. STOMP 프로토콜을 사용하여 서버와 연결 시작
stompClient.connect({}, () => {
console.log('Connected to WebSocket'); // 연결 성공 시 로그 출력
});
}
// 사용자가 특정 채팅방에 참여하는 기능을 구현하는 함수
function joinRoom() {
if (stompClient) { // WebSocket 연결이 활성화된 상태인지 확인
const roomInput = document.getElementById('roomInput'); // 입력된 채팅방 이름 가져오기
currentRoom = roomInput.value; // 현재 채팅방 이름을 변수에 저장
if (currentRoom) { // 채팅방 이름이 유효한 경우
// 1. STOMP 클라이언트가 해당 채팅방 주제를 구독
// /topic/{roomName} 경로를 구독하여 해당 방의 메시지를 실시간으로 수신
stompClient.subscribe(`/topic/${currentRoom}`, (response) => {
showMessage(response.body); // 메시지가 수신되면 화면에 표시
});
// 2. 구독이 성공했음을 사용자에게 알림
alert(`Joined room: ${currentRoom}`);
}
}
}
// 사용자가 메시지를 보내는 기능을 구현하는 함수
function sendMessage() {
if (stompClient && currentRoom) { // WebSocket 연결과 채팅방이 활성화된 경우
const messageInput = document.getElementById('messageInput'); // 입력된 메시지 가져오기
const message = messageInput.value; // 메시지 값 저장
// 1. STOMP 클라이언트를 통해 메시지를 서버로 전송
// /app/chat/{roomName} 경로로 메시지를 송신
stompClient.send(`/app/chat/${currentRoom}`, {}, message);
// 2. 입력창 초기화
messageInput.value = '';
}
}
// 수신된 메시지를 화면에 표시하는 함수
function showMessage(message) {
const messagesDiv = document.getElementById('messages'); // 메시지 표시 영역
const messageElement = document.createElement('div'); // 새로운 메시지 요소 생성
// 메시지 내용을 div 요소에 추가
messageElement.textContent = message;
// 메시지를 화면에 추가
messagesDiv.appendChild(messageElement);
}
// 페이지 로드 시 WebSocket 연결 자동 설정
connect();
</script>
</div>
</body>
</html>
728x90
'Spring Boot' 카테고리의 다른 글
[Spring Boot] Slf4j와 Logback (1) | 2024.11.29 |
---|---|
[Spring Boot] Lombok과 직렬화/역직렬화 (0) | 2024.11.25 |
[Spring Boot] AccessToken 및 RefreshToken 인증 구현하기 (1) | 2024.11.21 |
[Spring Boot] 스프링 시큐리티 설정 (5) | 2024.11.09 |
[Spring Boot] @Configuration @Bean 사용법 (3) | 2024.11.08 |