If at first you don't succeed, try again

[개발] 순수 WebSocket으로 채팅 구현 feat.Postman 본문

개발

[개발] 순수 WebSocket으로 채팅 구현 feat.Postman

웅지니어링 2025. 3. 17. 21:31

* 개요

Springframework의 websocket을 통해서 간단한 채팅을 구현해볼 예정이다. 채팅이 실제로 잘 동작하는지는 Postman을 통해 확인한다.

 

* WebSocketConfig 작성

코드를 먼저 작성한 뒤 부연 설명을 하겠다.

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;

@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
    private final SimpleWebSocketHandler simpleWebSocketHandler;

    public WebSocketConfig(SimpleWebSocketHandler simpleWebSocketHandler) {
        this.simpleWebSocketHandler = simpleWebSocketHandler;
    }


    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(simpleWebSocketHandler, "/connect")
                .setAllowedOrigins("http://localhost:3000");
    }
}

이 파일은 WebSocket에 대한 정보를 담은 Config 파일이라고 할 수 있다.

WebSocket에 대한 설정을 담고, WebSocketConfigurer을 implements한다.

그리고 @EnableWebSocket을 통해 WebSocket 기능을 활성화한다.

생성자를 통해 의존성을 주입하고, WebSocketConfigurer의 메서드를 오버라이딩한다.

connect의 url로 websocket 연결 요청이 들어오면, 핸들러 클래스(simpleWebSocketHandler)가 처리할 것이다.

(엔드포인트 설정)

그리고 cors를 설정해주는데, http://localhost:3000에 대해서만 출처를 허용한다.

이제 핸들러 클래스의 코드를 작성해보자.

 

* SimpleWebSocketHandler 작성

@Component
@Slf4j
public class SimpleWebSocketHandler extends TextWebSocketHandler {
    private final Set<WebSocketSession> sessions = ConcurrentHashMap.newKeySet();

    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        sessions.add(session);
        log.info("connected : {}", session.getId());
    }

    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        String payload = message.getPayload();
        log.info("received message : {}", payload);
        for (WebSocketSession s :  sessions) {
            if (s.isOpen()) {
                s.sendMessage(new TextMessage(payload));
            }
        }
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        sessions.remove(session);
        System.out.println("disconnected!!");
    }

}

SimpleWebSocketHandler는 웹 소켓 연결 요청이 들어왔을 대, 이를 처리할 클래스다.

채팅을 구현할 것이기에, TextWebSocketHandler를 상속했다.

연결된 세션 관리는 thread-safe한 Set 자료구조를 사용하고, 구현체는 ConcurrentHashMap을 사용했다.

ConcurrentHashMap을 사용한 이유는 동시성을 고려했기 때문이다.

동작 원리를 알아보자.

  1. afterConnectionEstablished 메서드를 통해 세션을 관리하는 Set에 세션을 담고, @Slf4j를 통한 로그를 출력한다.
  2. handleTextMessage 메서드를 통해 수신된 message의 payload 로그를 출력하고, 서버에 대한 응답 message를 발신한다.
  3. afterConnectionClosed 메서드를 통해서 세션을 종료한다.

잘 동작할까? Postman을 통해 확인해보자!

 

* Postman으로 채팅 구현 확인

Postman에 접속한 다음, 

url을 ws://localhost:8080/connect로 설정해둔다.

앗 여기서 url이 왜 http로 시작하지 않는걸까?

http 프로토콜이 아니라 ws 프로토콜을 사용하기 때문이다.

양방향 채팅을 할 것이기에, 똑같은 url의 client를 하나 더 만든다.

자, Spring 서버를 가동시킨 뒤 Connect를 눌러보자.

잘 connect 된 것을 확인할 수 있다.

서버 쪽의 로그도 확인해보자.

2개의 sessionId가 있는 것을 확인할 수 있다.

메시지를 보내보자!

"안녕하세요 ~" 메시지가 잘 전송되었다. 다른 client 쪽에서도 메시지를 보내보자.

"반갑습니다 !" 메시지도 잘 전송된 것을 확인할 수 있다!!

그럼 마지막으로 disconnect를 누른 뒤, 어떻게 되는지 확인해보자.

세션이 종료되었고, disconnected!! 라는 로그도 잘 출력되었다.

'개발' 카테고리의 다른 글

[개발] STOMP를 사용한 config 구현  (0) 2025.03.27
[개발] IntelliJ 윈도우 단축키  (0) 2022.11.21