Files
spring-boot-examples/docs/webflux/11_웹플럭스와 웹소켓.md
2025-04-08 19:56:24 +09:00

163 lines
6.7 KiB
Markdown

아래는 **"스프링부트 웹플럭스 시리즈"**의 **11장: 웹플럭스와 웹소켓"**에 대한 초안입니다. 10장의 마이크로서비스 기반을 활용하여 웹소켓을 통해 실시간 통신을 구현하며, 간단한 채팅 애플리케이션 예제를 포함했습니다. 코드도 간략히 유지하며 초보자가 따라 하기 쉽게 자연스러운 문체로 작성했습니다.
---
## 11. 웹플럭스와 웹소켓
10장에서 마이크로서비스를 구축하며 웹플럭스의 비동기 특성을 실감했습니다. 이번 장에서는 한 단계 더 나아가 웹소켓(WebSocket)을 활용해 실시간 통신을 구현해보겠습니다. 웹플럭스와 웹소켓은 실시간 데이터 전송에 최적화된 조합으로, 채팅 같은 기능을 쉽게 만들 수 있습니다. 간단한 예제를 통해 실습해보죠. 준비되셨나요?
### 실시간 통신을 위한 웹소켓 구현
웹소켓은 클라이언트와 서버 간 양방향 통신을 가능하게 하는 프로토콜입니다. HTTP와 달리 연결을 유지하며, 데이터를 주고받는 데 지연이 적습니다. 웹플럭스는 이를 기본 지원하니, 추가 의존성 없이 바로 시작할 수 있습니다.
10장의 User Service를 확장해 웹소켓 기반 채팅 기능을 추가해보겠습니다. 먼저, 웹소켓 핸들러를 만듭니다.
#### 웹소켓 핸들러 작성
`src/main/java/com/example/demo``ChatWebSocketHandler` 클래스를 추가합니다:
```java
package com.example.demo;
import org.springframework.web.reactive.socket.WebSocketHandler;
import org.springframework.web.reactive.socket.WebSocketSession;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.time.Duration;
public class ChatWebSocketHandler implements WebSocketHandler {
private final Flux<String> messageFlux;
public ChatWebSocketHandler() {
// 간단한 메시지 스트림 예제
this.messageFlux = Flux.interval(Duration.ofSeconds(1))
.map(i -> "Message " + i);
}
@Override
public Mono<Void> handle(WebSocketSession session) {
// 클라이언트로부터 메시지 수신
Flux<String> input = session.receive()
.map(message -> "Echo: " + message.getPayloadAsText());
// 클라이언트로 메시지 전송
return session.send(messageFlux.mergeWith(input)
.map(session::textMessage));
}
}
```
- `messageFlux`: 서버에서 주기적으로 보내는 메시지 스트림 (예시용).
- `handle`: 클라이언트 메시지를 받아 에코로 반환하고, 서버 메시지도 함께 전송.
#### 웹소켓 라우팅 설정
`src/main/java/com/example/demo``WebSocketConfig`를 추가합니다:
```java
package com.example.demo;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.HandlerMapping;
import org.springframework.web.reactive.handler.SimpleUrlHandlerMapping;
import org.springframework.web.reactive.socket.WebSocketHandler;
import java.util.HashMap;
import java.util.Map;
@Configuration
public class WebSocketConfig {
@Bean
public HandlerMapping webSocketMapping() {
Map<String, WebSocketHandler> map = new HashMap<>();
map.put("/chat", new ChatWebSocketHandler());
SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping();
mapping.setUrlMap(map);
mapping.setOrder(-1); // 다른 매핑보다 우선
return mapping;
}
}
```
- `/chat` 경로로 웹소켓 연결을 처리.
### 웹플럭스와 웹소켓의 조합 예제
User Service (`port: 8081`)에 위 코드를 추가한 뒤 실행합니다. 이제 클라이언트에서 웹소켓 연결을 테스트할 수 있습니다.
#### 클라이언트 테스트
간단한 HTML/JS 클라이언트를 만들어 보죠. `src/main/resources/static``index.html`을 추가합니다:
```html
<!DOCTYPE html>
<html>
<head>
<title>WebSocket Chat</title>
</head>
<body>
<input id="message" type="text">
<button onclick="sendMessage()">Send</button>
<div id="messages"></div>
<script>
const socket = new WebSocket("ws://localhost:8081/chat");
const messagesDiv = document.getElementById("messages");
socket.onmessage = function(event) {
const msg = document.createElement("p");
msg.textContent = event.data;
messagesDiv.appendChild(msg);
};
function sendMessage() {
const input = document.getElementById("message");
socket.send(input.value);
input.value = "";
}
</script>
</body>
</html>
```
`http://localhost:8081/index.html`에 접속하면:
1. 서버에서 1초마다 "Message 0", "Message 1" 등이 표시.
2. 입력창에 메시지를 입력하고 Send 버튼을 누르면 "Echo: [입력값]" 반환.
### 활용 사례 (채팅 애플리케이션 등)
위 예제는 기본적인 에코 서버지만, 이를 확장하면 실시간 채팅 애플리케이션을 만들 수 있습니다:
- **다중 사용자 지원**: `Flux`를 공유 가능한 스트림으로 만들어 모든 클라이언트에 브로드캐스트.
```java
private final Sinks.Many<String> messageSink = Sinks.many().multicast().onBackpressureBuffer();
private final Flux<String> messageFlux = messageSink.asFlux();
@Override
public Mono<Void> handle(WebSocketSession session) {
Flux<String> input = session.receive()
.map(message -> session.getId() + ": " + message.getPayloadAsText())
.doOnNext(messageSink::tryEmitNext);
return session.send(messageFlux.map(session::textMessage));
}
```
- **상태 관리**: Redis나 데이터베이스로 채팅 기록 저장.
- **인증**: 스프링 시큐리티로 웹소켓 연결에 토큰 기반 인증 추가.
채팅 외에도 주식 시세 업데이트, 실시간 알림 등 다양한 활용이 가능합니다.
### 테스트해보기
1. User Service 실행.
2. 브라우저에서 `http://localhost:8081/index.html` 열기.
3. 메시지 입력 후 Send 버튼 클릭 → 서버 메시지와 에코 확인.
### 마무리
웹플럭스와 웹소켓으로 실시간 통신의 세계에 입문했습니다. 비동기 스트림과 양방향 연결이 얼마나 강력한지 느끼셨나요? 다음 장에서는 웹플럭스의 현재와 미래를 돌아보며, 이 기술의 여정을 마무리하겠습니다. 이번 실습으로 실시간 애플리케이션의 가능성을 열어보셨길 바랍니다!
---
이 장은 웹소켓의 기본 구현과 채팅 예제를 중심으로 구성했으며, 실습과 활용 사례를 간략히 다뤘습니다. 추가 기능이나 수정이 필요하면 말씀해주세요!