1+ package com .dmu .debug_visual .config ;
2+
3+ import com .dmu .debug_visual .websocket .dto .SystemMessage ;
4+ import com .dmu .debug_visual .websocket .service .RoomService ;
5+ import lombok .RequiredArgsConstructor ;
6+ import lombok .extern .slf4j .Slf4j ;
7+ import org .springframework .context .event .EventListener ;
8+ import org .springframework .messaging .simp .SimpMessageSendingOperations ;
9+ import org .springframework .messaging .simp .stomp .StompHeaderAccessor ;
10+ import org .springframework .stereotype .Component ;
11+ import org .springframework .web .socket .messaging .SessionDisconnectEvent ;
12+ import org .springframework .web .socket .messaging .SessionSubscribeEvent ;
13+
14+ import java .util .Map ;
15+ import java .util .Objects ;
16+
17+ @ Slf4j
18+ @ Component
19+ @ RequiredArgsConstructor
20+ public class WebSocketEventListener {
21+
22+ private final SimpMessageSendingOperations messagingTemplate ;
23+ private final RoomService roomService ;
24+
25+ // 사용자가 특정 방을 구독할 때(입장) 호출되는 메서드
26+ @ EventListener
27+ public void handleWebSocketSubscribeListener (SessionSubscribeEvent event ) {
28+ StompHeaderAccessor headerAccessor = StompHeaderAccessor .wrap (event .getMessage ());
29+ Map <String , Object > sessionAttributes = headerAccessor .getSessionAttributes ();
30+
31+ String destination = headerAccessor .getDestination ();
32+ if (destination != null && destination .startsWith ("/topic/room/" )) {
33+ String roomId = destination .split ("/" )[3 ];
34+ String userName = (String ) Objects .requireNonNull (sessionAttributes ).get ("userName" );
35+
36+ String userId = (String ) sessionAttributes .get ("userId" );
37+
38+ // ✨ 중요: 세션에 현재 사용자가 어느 방에 들어갔는지 기록합니다.
39+ if (userId != null ) {
40+ roomService .addParticipant (roomId , userId );
41+ }
42+
43+ log .info ("[입장] 사용자: {}, 방: {}" , userName , roomId );
44+ SystemMessage chatMessage = SystemMessage .builder ()
45+ .roomId (roomId )
46+ .senderName ("System" )
47+ .content (userName + "님이 입장했습니다." )
48+ .build ();
49+
50+
51+ messagingTemplate .convertAndSend ("/topic/room/" + roomId + "/system" , chatMessage );
52+ }
53+ }
54+
55+ // 사용자의 웹소켓 연결이 끊어졌을 때(퇴장) 호출되는 메서드
56+ @ EventListener
57+ public void handleWebSocketDisconnectListener (SessionDisconnectEvent event ) {
58+ StompHeaderAccessor headerAccessor = StompHeaderAccessor .wrap (event .getMessage ());
59+ Map <String , Object > sessionAttributes = headerAccessor .getSessionAttributes ();
60+
61+ if (sessionAttributes != null ) {
62+ String userName = (String ) sessionAttributes .get ("userName" );
63+
64+ // ✨ 중요: 세션에서 아까 저장해둔 roomId를 꺼냅니다.
65+ String roomId = (String ) sessionAttributes .get ("roomId" );
66+
67+ if (userName != null && roomId != null ) {
68+ log .info ("[퇴장] 사용자: {}, 방: {}" , userName , roomId );
69+
70+ SystemMessage chatMessage = SystemMessage .builder ()
71+ .roomId (roomId )
72+ .senderName ("System" )
73+ .content (userName + "님이 퇴장했습니다." )
74+ .build ();
75+
76+ messagingTemplate .convertAndSend ("/topic/room/" + roomId + "/system" , chatMessage );
77+ }
78+ }
79+ }
80+ }
0 commit comments