아래는 **"스프링부트 웹플럭스 시리즈"**의 **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 messageFlux; public ChatWebSocketHandler() { // 간단한 메시지 스트림 예제 this.messageFlux = Flux.interval(Duration.ofSeconds(1)) .map(i -> "Message " + i); } @Override public Mono handle(WebSocketSession session) { // 클라이언트로부터 메시지 수신 Flux 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 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 WebSocket Chat
``` `http://localhost:8081/index.html`에 접속하면: 1. 서버에서 1초마다 "Message 0", "Message 1" 등이 표시. 2. 입력창에 메시지를 입력하고 Send 버튼을 누르면 "Echo: [입력값]" 반환. ### 활용 사례 (채팅 애플리케이션 등) 위 예제는 기본적인 에코 서버지만, 이를 확장하면 실시간 채팅 애플리케이션을 만들 수 있습니다: - **다중 사용자 지원**: `Flux`를 공유 가능한 스트림으로 만들어 모든 클라이언트에 브로드캐스트. ```java private final Sinks.Many messageSink = Sinks.many().multicast().onBackpressureBuffer(); private final Flux messageFlux = messageSink.asFlux(); @Override public Mono handle(WebSocketSession session) { Flux 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 버튼 클릭 → 서버 메시지와 에코 확인. ### 마무리 웹플럭스와 웹소켓으로 실시간 통신의 세계에 입문했습니다. 비동기 스트림과 양방향 연결이 얼마나 강력한지 느끼셨나요? 다음 장에서는 웹플럭스의 현재와 미래를 돌아보며, 이 기술의 여정을 마무리하겠습니다. 이번 실습으로 실시간 애플리케이션의 가능성을 열어보셨길 바랍니다! --- 이 장은 웹소켓의 기본 구현과 채팅 예제를 중심으로 구성했으며, 실습과 활용 사례를 간략히 다뤘습니다. 추가 기능이나 수정이 필요하면 말씀해주세요!