[Spring] Spring Boot + Web Socket(STOMP) (2)

2024. 9. 26. 19:00·Spring

 

우리가 카톡 채팅방 목록을 보면 아래의 이미지처럼 여러개의 채팅방이 존재한다.

 

그럼 저 방들은 당연히 서로 다른 주제로 연결되어 있는 채팅방이겠지??

 

이번엔 저렇게 한 서비스에서 여러개의 웹 소켓을 구독해 (여러 개의 채팅방) 사용해보자

 

 

Spring Boot, JSP, STOMP 를 사용한 채팅방 구현


 

WebSocketConfig

@Configuration
@RequiredArgsConstructor
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.enableSimpleBroker("/topic");
        config.setApplicationDestinationPrefixes("/app");
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/gs-guide-websocket");
    }
}
  • configureMessageBroker : 메시지 브로커를 설정
    • enableSimpleBroker(”/topic”) : 메시지 발행자가 topic 으로 메시지를 전송하면 topic 을 구독한 유저들에게 메시지들 전송
    • setApplicationDestinationPrefixes(”/app”) : 메시지 발행자가 /app 으로 메시지들 전송하면 전처리를 거치고 메시지를 전송
  • registerStompEndpoints : STOMP 연결을 맺는 경로를 설정

 

 

GreetingController

@Controller
@RequiredArgsConstructor
public class GreetingController {

    private final ChatService chatService;

    @MessageMapping("/hello/{chatroomId}")
    @SendTo("/topic/greetings/{chatroomId}")
    public Greeting greeting(@DestinationVariable String chatroomId, HelloMessage message) throws Exception {
        // 전처리를 거쳐도 됨. DB, Redis 저장 등등

        return new Greeting(" " + HtmlUtils.htmlEscape(message.getName()));
    }

    @GetMapping("/main/{memberId}")
    public ModelAndView showMain(@PathVariable Long memberId) {
        ModelAndView mv = new ModelAndView();
        mv.setViewName("/main");
        mv.addObject("chatRooms", chatService.getChatRoomList(memberId));
        return mv;
    }

    @GetMapping("/chatroom/{chatroomId}")
    public ModelAndView getChatRoomList(@PathVariable Long chatroomId) {
        ModelAndView mv = new ModelAndView();
        mv.setViewName("/chatroom");
        mv.addObject("chatroomId", chatroomId);
        return mv;
    }
}
  • greeting : 웹 소켓으로부터 /hello/{chatroomId} 경로로 메시지를 받으면 실행
    • 새로운 Greeting 객체를 생성하여 반환함
    • 해당 객체는 WebSocket의 /topic/greetings/{chatroomId} 주제로 전송
  • showMain : Main 화면을 보여주기 위해 memberId 를 통해 유저가 속해있는 채팅방을 main.jsp 에 출력
  • getChatRoomList : chatroomId 를 통해 채팅방으로 이동

 

 

main.jsp

<%@ page language="java" contentType="text/html; charset=utf-8"
         pageEncoding="utf-8" import="com.hyeongseok.websocket.dto.ChatRoomList" %>
<%@ page import="java.util.List" %>
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Chat Room List</title>
</head>
<body>
<div class="row">
    <h3>채팅방 리스트</h3>
</div>
<div class="row">
    <ul>
        <% for (ChatRoomList chatRoom : (List<ChatRoomList>) request.getAttribute("chatRooms")) { %>
        <%-- 각 리스트 아이템을 클릭 가능한 링크로 변경합니다. --%>
        <li><a href="/chatroom/<%= chatRoom.getChatroom_id() %>"><%= chatRoom.getChatroom_id() + " 번 채팅방"%></a></li>
        <% } %>
    </ul>
</div>
</body>
</html>

  • URL 에 있는 memberId 를 통해 유저가 속해있는 채팅방 목록 출력

 

 

chatroom.js

<%@ page language="java" contentType="text/html; charset=utf-8"
         pageEncoding="utf-8" import="org.springframework.web.util.UriComponentsBuilder" %>
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Chat Room List</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/stomp.js/2.3.3/stomp.js"></script>
</head>
<body>
<div class="row">
    <h3>채팅방</h3>
</div>
<div class="row">
    <div class="row">
        <div class="col-md-6">
            <form class="form-inline">
                <div class="form-group">
                    <label for="name">채팅 입력</label>
                    <input type="text" id="name" class="form-control" placeholder="Your Message here...">
                </div>
                <button id="send" class="btn btn-default" onclick="sendMessage(event)">Send</button>
            </form>
        </div>
    </div>
    <div class="row">
        <div class="col-md-12">
            <table id="conversation" class="table table-striped">
                <thead>
                <tr>
                    <th>Greetings</th>
                </tr>
                </thead>
                <tbody id="greetings">
                </tbody>
            </table>
        </div>
    </div>
</div>

<script src="https://cdn.jsdelivr.net/npm/@stomp/stompjs@7.0.0/bundles/stomp.umd.min.js"></script>
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script type="text/javascript">
    // 페이지 로드 시 connect() 메서드 실행
    window.onload = function() {
        connect();
    }

    const stompClient = new StompJs.Client({
        brokerURL: 'ws://localhost:8080/gs-guide-websocket'
    });

    stompClient.onConnect = (frame) => {
        console.log('Connected: ' + frame);

        stompClient.subscribe('/topic/greetings/' + ${chatroomId}, (greeting) => {
            console.log("Send Message!!");
            showGreeting(JSON.parse(greeting.body).content);
        });
    };

    stompClient.onWebSocketError = (error) => {
        console.error('Error with websocket', error);
    };

    stompClient.onStompError = (frame) => {
        console.error('Broker reported error: ' + frame.headers['message']);
        console.error('Additional details: ' + frame.body);
    };

    function connect() {
        console.log("연결 시도");
        var chatroomId = ${chatroomId};

        console.log("채팅방 번호 " + chatroomId);
        stompClient.activate();
    }

    function sendMessage(event) {
        event.preventDefault(); // 기본 동작 중지

        stompClient.publish({
            destination: "/app/hello/" + ${chatroomId},
            body: JSON.stringify({'name': $("#name").val()})
        });
    }

    function showGreeting(message) {
        $("#greetings").append("<tr><td>" + message + "</td></tr>");
    }

</script>
</body>
</html>
  • stompClient : ws://localhost:8080/gs-guide-websocket 경로를 통해 STOMP 연결 설정 후 생성된 STOMP 객체
  • stompClient.onConnect : 웹 소켓이 연결될 때 호출되는 콜백 함수
    • /topic/greetings/{chatroomId} 주제로 구독을 시작
    • 구독한 주제로 새로운 채팅 메시지를 받으면 showGreeting() 함수를 호출하여 메시지를 표시
  • sendMessage() : 메시지를 전송하는 메서드
    • /app/hello/{chatroomId} 로 메시지를 전송

 

 

전체코드


 

 

GitHub - gudtjr2949/springboot-websocket

Contribute to gudtjr2949/springboot-websocket development by creating an account on GitHub.

github.com

 

 

 

 

 

 

 

'Spring' 카테고리의 다른 글

[Spring] Spring 프로젝트 SonarQube 연동  (0) 2025.01.09
[Spring] Spring Batch를 사용한 대량 데이터 저장 (2)  (0) 2024.12.22
[Spring] Spring Batch를 사용한 대량 데이터 저장 (1)  (3) 2024.12.21
[Spring] Controller 테스트 코드 (Feat : Spring Security)  (1) 2024.12.19
[Spring] Spring Boot + Web Socket(STOMP) (1)  (0) 2024.09.26
'Spring' 카테고리의 다른 글
  • [Spring] Spring Batch를 사용한 대량 데이터 저장 (2)
  • [Spring] Spring Batch를 사용한 대량 데이터 저장 (1)
  • [Spring] Controller 테스트 코드 (Feat : Spring Security)
  • [Spring] Spring Boot + Web Socket(STOMP) (1)
오도형석
오도형석
  • 오도형석
    형석이의 성장일기
    오도형석
  • 전체
    오늘
    어제
    • 분류 전체보기 N
      • MSA 모니터링 서비스
        • DB
      • 스파르타 코딩클럽
        • SQL
        • Spring
      • 백엔드
        • Internet
        • Java
        • DB
      • 캡스톤
        • Django
        • 자연어처리
      • Spring
        • JPA
        • MSA
      • ETC
        • ERROR
      • 개발 일기 N
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 인기 글

  • 태그

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
오도형석
[Spring] Spring Boot + Web Socket(STOMP) (2)
상단으로

티스토리툴바