WebSocket, Stomp로 통신 해보기 (1)

이형석·2024년 11월 27일

개념

WebSocket

  • 웹 환경에서 동작하는 통신 프로토콜로, HTTP를 업그레이드하여 전이중(Full-Duplex) 통신을 제공합니다.
  • 일반적으로 클라이언트는 브라우저 또는 웹 클라이언트이고, 서버는 WebSocket 서버입니다.
  • HTTP 요청을 통해 WebSocket 연결을 시작하며, 연결이 확립되면 지속적인 양방향 통신이 가능합니다.

ServerSocket/Socket과 WebSocket의 주요 차이점

구분ServerSocket/SocketWebSocket
프로토콜TCP/IPWebSocket (HTTP 업그레이드)
연결 방식낮은 수준의 네트워크 연결고수준 웹 통신
지속성지속 연결지속 연결
데이터 송수신스트림 기반 통신프레임 기반 통신
웹 브라우저 지원직접 지원하지 않음브라우저에서 기본적으로 지원 (HTML5)
사용 용도일반적인 네트워크 통신 (앱, 서버 등)웹 애플리케이션의 실시간 통신

요약

ServerSocket과 Socket은 일반적인 네트워크 통신을 위해 사용되며, 프로토콜 레벨에서 작동합니다.
WebSocket은 웹 애플리케이션의 실시간 통신을 위해 설계된 고수준 프로토콜로, 효율적이고 간편한 실시간 통신이 필요할 때 적합합니다.
만약 웹 기반 실시간 애플리케이션을 개발하려면 WebSocket이 적합하고, 네트워크 프로그래밍을 다룰 때는 Socket을 사용할 수 있습니다.


WebSocket 구현

1. WebSocket 서버 만들기

1. 의존성 추가

implementation 'org.springframework.boot:spring-boot-starter-websocket'

2. Configuration 클래스 설정

@Configuration
@EnableWebSocket
public class WebSocketServerConfig implements WebSocketConfigurer {
    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(new WebSocketServerHandler(), "/ws").setAllowedOrigins("*");
    }
}

3. WebSocket 서버 엔드포인트 구현

@Component
public class WebSocketServerHandler extends TextWebSocketHandler {
    @Override
    public void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        System.out.println("받은 메시지: " + message.getPayload());
        // 클라이언트에 응답
        session.sendMessage(new TextMessage("Hello Client!"));
    }
}

서버를 실행하고, ws://localhost:8080/ws로 연결 요청을 받습니다.

2. WebSocket 클라이언트 구현 (다른 서버)

1. 의존성 추가

implementation 'org.springframework.boot:spring-boot-starter-websocket'

2. WebSocket 클라이언트 구현

@Component
public class WebSocketClient {
    public void connect() {
        StandardWebSocketClient client = new StandardWebSocketClient();
        client.doHandshake(new ClientHandler(), "ws://localhost:8080/ws");
    }

    private static class ClientHandler extends TextWebSocketHandler {
        @Override
        public void afterConnectionEstablished(org.springframework.web.socket.WebSocketSession session) throws Exception {
            System.out.println("서버 연결 성공!");
            session.sendMessage(new TextMessage("Hello Server!"));
        }

        @Override
        public void handleTextMessage(org.springframework.web.socket.WebSocketSession session, TextMessage message) throws Exception {
            System.out.println("서버로부터 받은 메시지: " + message.getPayload());
        }
    }
}

3. 애플리케이션 실행 시 WebSocket 클라이언트 연결

@SpringBootApplication
public class WebSocketClientApp implements CommandLineRunner {

    private final WebSocketClient webSocketClient;

    public WebSocketClientApp(WebSocketClient webSocketClient) {
        this.webSocketClient = webSocketClient;
    }

    public static void main(String[] args) {
        SpringApplication.run(WebSocketClientApp.class, args);
    }

    @Override
    public void run(String... args) {
        webSocketClient.connect();
    }
}

클라이언트 서버를 실행하면 ws://localhost:8080/ws로 연결을 시도하고, 메시지를 주고받습니다.


Stomp 구현

Stomp

  • WebSocket 위에서 동작하는 고수준 프로토콜
  • Json형태의 메시지를 자동 Parsing 가능

1. 의존성 추가

(WebSocket과 같음)

implementation 'org.springframework.boot:spring-boot-starter-websocket'

2. WebSocket Configuration 클래스 작성

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketServerConfig implements WebSocketMessageBrokerConfigurer {

    @Override
    //초기 연결 설정 메서드
    public void registerStompEndpoints(StompEndpointRegistry registry) {

        //오프닝 엔드포인트 설정
        //최초 연결 요청 URI -> ws://localhost:8080/websocket-connect
        registry.addEndpoint("/websocket-connect")
                //CORS 허용
                .setAllowedOrigins("*");
    }

    @Override
    // 발행 endpoint 와 구독 endpoint 관련 설정 메서드
    public void configureMessageBroker(MessageBrokerRegistry config) {

        //메시지 발행자가 전달할 채널의 prefix
        // ex) /chat 이라는 채널에 메시지 전달 -> /pub/chat
        config.setApplicationDestinationPrefixes("/pub");

        //구독자들이 구독할 채널의 prefix
        // ex) /chat 이라는 채널을 구독하려면 -> /sub/chat
        config.enableSimpleBroker("/sub");

        // /chat 이라는 url 은 컨트롤러의 @MessageMapping 에서 설정
    }
}

3. WebSocket 컨트롤러 클래스 작성

@Controller
public class MessageController {

    @MessageMapping("/chat")    // /chat 채널 명   _/pub/chat 으로 발행된 메시지 처리
    @SendTo("/sub/chat")    // /chat 을 구독한 사용자에게 전달
    public ChatMessageResponse sendMessage(ChatMessageRequest request) {
    //DTO : ChatMessageRequest _JSON 타입 메시지 요청, DTO 로 자동 직렬화

		return new ChatMessageResponse(request.sender(), request.content());
    }
    //chat 이라는 채널을 쓴다고 가정
    //보내는 쪽은 /pub/chat 으로 보냄
    //받는 쪽은 /sub/chat 을 구독
}

DTO 참고

public record ChatMessageRequest(
        String sender,
        String content
) {}
public record ChatMessageResponse(
        String sender,
        String content

) {}

4. 로그 설정

application.properties

logging.level.org.springframework.web.socket=DEBUG
logging.level.org.springframework.messaging.simp=DEBUG

5. 테스트

테스트 사이트
https://jiangxy.github.io/websocket-debug-tool/

1. 연결

  • URL - 최초 연결 엔드 포인트 입력
    ex) ws://localhost:8080/websocket-connect
  • Connect Type - STOMP 체크
  • Connect

2. 구독

  • STOMP subscribe destination - 구독 URI 입력
    ex) /sub/chat
  • Subscribe

3. 발신

  • STOMP send destination - 발행 URI 입력
    ex) /pub/chat
  • Message Content: 웹소켓 컨트롤러의 DTO에 따른 JSON 형식 메시지 입력
    ex) {"sender":"hongildong","content":"Hello!"}
  • Send

참고
[10분 테코톡] 트레의 스프링에서 STOMP로 채팅 구현하기
websocket( + STOMP)를 온라인에서 디버그하자

profile
금융IT 개발자

0개의 댓글