spring-boot / websocket

최경현·2024년 8월 23일

프로젝트를 진행하면서 restAPI와 websocket을 병행해서 사용할 일이 생겼다.

일단 웹소켓을 터미널에서 설치해줘야한다.

npm install -g wscat

그리고 라이브러리 적용

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

웹 소켓 설치.
그리고 websocket메시지를 처리할 클래스를 하나 만들어 줘야한다.

@Component
@RequiredArgsConstructor
//    웹소켓 메세지를 처리하는 클래스
public class WebSoketMessageHandler extends TextWebSocketHandler {
    //    사용자 id와 웹소켓 세션을 매핑하는 hashmap, 사용자와 연결된 세션 추적
    HashMap<String, WebSocketSession> sessionMap = new HashMap<>();

    @Override
//    연결이 성립되었을 때 호출하는 메서드
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
//        웹소켓 세션으로부터 사용자 id를 찾아냄
        String userId = searchUserName(session);
//        세션맵에 사용자 id와 웹소켓 세션 추가
        sessionMap.put(userId, session);
    }

    @Override
//    연결이 닫혔을 때 호출되는 메서드
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        // 세션에서 사용자 id 호출
        String userId = searchUserName(session);
//        세션맵에서 사용자 id 제거
        sessionMap.remove(userId);
    }

    // 웹소켓 세션의 URI를 파싱하여 사용자 id를 추출하는 메서드
    public String searchUserName(WebSocketSession session) {
//        URL파싱
        UriComponents uriComponents = UriComponentsBuilder.fromUriString(session.getUri().toString()).build();
//        쿼리 매개변수에 uid값을 추출, 웹소켓에 연결할 때 "uid" 파라미터를 붙여서 보내야 searchUserName 메소드가 작동
        return uriComponents.getQueryParams().getFirst("uid");
    }

    // 주문 상태를 브로드캐스트하는 메서드
    public void broadcastOrderUpdate(OrderManagementDto orderManagementDto) {
        String orderUpdateMessage = convertToJson(orderManagementDto);
        System.out.println("잘 될거야 :" + orderUpdateMessage);
        for (WebSocketSession session : sessionMap.values()) {
            try {
//                세션을 통해 메세지 전송
                System.out.println("진짜 잘 보내질거야 :" + session.getId());
                session.sendMessage(new TextMessage(orderUpdateMessage));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    // DTO 객체를 JSON 문자열로 변환하는 메서드
    private String convertToJson(OrderManagementDto orderManagementDTO) {
        // 실제 구현에서는 Jackson 또는 Gson 등을 사용하여 JSON 변환
        try {
            ObjectMapper objectMapper = new ObjectMapper();
            objectMapper.registerModule(new JavaTimeModule());
            return objectMapper.writeValueAsString(orderManagementDTO);
        } catch (Exception e) {
            e.printStackTrace();
            return "{}";
        }
    }
}

설명은 주석으로 적어놨으니 참고하길 바란다.

websocketconfig클래스를 하나 만들어줘야한다.
웹소켓 설정을 커스텀마이징 하기 위해서이다.

@EnableWebSocket
@Configuration
@RequiredArgsConstructor
//    웹소켓 설정 커스텀마이징
public class WebsocketConfig implements WebSocketConfigurer {

//    웹소켓 메세지를 처리
    private final WebSoketMessageHandler webSoketMessageHandler;

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
//        /orders 엔드포인트에 핸들러로 등록 후 CORS 요청 허용
        registry.addHandler(webSoketMessageHandler, "/ws/orders").setAllowedOrigins("*");
    }

}

난 터미널에서 웹소켓통신 테스트를 진행하였다.

wscat -c 'ws://localhost:8080/ws/orders?uid=회원아이디' 

터미널에서 로그인한 유저 아이디랑 웹소켓 통신을 하기 위해 연결을 하였다.
wscat을 이용해서 테스트를 진행하였다.

// put이든 get이든 post든 알아서 설정
http://localhost:8080/api/v1/orders/create

이렇게 통신하면은 잘 보내진다.

대충 기억나는대로 끄적인거라 부족한 정보가 많다. 나머지 정보는 알아서 찾아보길 바란다.

profile
ㅇㅇ

0개의 댓글