2424import java .util .stream .Collectors ;
2525
2626/**
27- * - 방 생성, 입장, 퇴장 로직 처리
28- * - 멤버 권한 관리 (승격, 강등, 추방)
29- * - 방 상태 관리 (활성화, 일시정지, 종료)
30- * - 방장 위임 로직 (방장이 나갈 때 자동 위임)
31- * - 실시간 참가자 수 동기화
32- * <p>
33- * - 모든 권한 검증을 서비스 레이어에서 처리
34- * - 비공개 방 접근 권한 체크
35- * - 방장/부방장 권한이 필요한 작업들의 권한 검증
36- * <p>
37- * 설정값 주입을 StudyRoomProperties를 통해 외부 설정 관리
27+ * 스터디룸 서비스 - 방 생성, 입장, 퇴장 및 실시간 상태 관리
28+ *
29+ * <h2>주요 기능:</h2>
30+ * <ul>
31+ * <li>방 생성, 입장, 퇴장 로직 처리</li>
32+ * <li>멤버 권한 관리 (승격, 강등, 추방)</li>
33+ * <li>방 상태 관리 (활성화, 일시정지, 종료)</li>
34+ * <li>방장 위임 로직 (방장이 나갈 때 자동 위임)</li>
35+ * <li>🆕 WebSocket 기반 실시간 참가자 수 및 온라인 상태 동기화</li>
36+ * </ul>
37+ *
38+ * <h2>권한 검증:</h2>
39+ * <ul>
40+ * <li>모든 권한 검증을 서비스 레이어에서 처리</li>
41+ * <li>비공개 방 접근 권한 체크</li>
42+ * <li>방장/부방장 권한이 필요한 작업들의 권한 검증</li>
43+ * </ul>
44+ *
45+ * <h2>🆕 WebSocket 연동 (PR #2):</h2>
46+ * <ul>
47+ * <li><b>권장 메서드:</b> {@link #getOnlineMembersWithWebSocket(Long, Long)} - WebSocket + DB 통합 조회</li>
48+ * <li><b>Deprecated:</b> {@link #getRoomMembers(Long, Long)} - DB만 조회 (하위 호환용으로만 유지)</li>
49+ * </ul>
50+ *
51+ * <p><b>중요:</b> 온라인 멤버 목록 조회 시 반드시 {@code getOnlineMembersWithWebSocket()}를 사용하세요.
52+ * 이 메서드는 실시간 WebSocket 연결 상태와 DB 정보를 결합하여 정확한 온라인 상태를 제공합니다.</p>
53+ *
54+ * <h2>설정값 관리:</h2>
55+ * <p>StudyRoomProperties를 통해 외부 설정 관리 (application.yml)</p>
56+ *
57+ * @since 1.0
58+ * @see WebSocketSessionManager WebSocket 세션 관리
59+ * @see WebSocketBroadcastService 실시간 브로드캐스트
3860 */
3961@ Service
4062@ RequiredArgsConstructor
@@ -370,24 +392,16 @@ public void changeUserRole(Long roomId, Long targetUserId, RoomRole newRole, Lon
370392 roomId , targetUserId , newRole , requesterId );
371393 }
372394
373- public List <RoomMember > getRoomMembers (Long roomId , Long userId ) {
374-
375- Room room = roomRepository .findById (roomId )
376- .orElseThrow (() -> new CustomException (ErrorCode .ROOM_NOT_FOUND ));
377-
378- if (room .isPrivate ()) {
379- boolean isMember = roomMemberRepository .existsByRoomIdAndUserId (roomId , userId );
380- if (!isMember ) {
381- throw new CustomException (ErrorCode .ROOM_FORBIDDEN );
382- }
383- }
384-
385- return roomMemberRepository .findOnlineMembersByRoomId (roomId );
386- }
387-
388395 /**
389- * 🆕 WebSocket 기반 온라인 멤버 목록 조회
390- * DB의 멤버 목록과 WebSocket 세션 상태를 결합하여 정확한 온라인 상태 제공
396+ * WebSocket 기반 온라인 멤버 목록 조회
397+ * DB의 멤버 목록과 WebSocket 세션 상태를 결합하여 온라인 상태 제공
398+ * WebSocket 연동 실패 시 DB 정보만으로 폴백하여 서비스 중단 방지
399+
400+ * @param roomId 조회할 방의 ID
401+ * @param userId 요청한 사용자의 ID (권한 체크용)
402+ * @return WebSocket 기반 실시간 온라인 멤버 목록 (RoomMemberResponse DTO)
403+ * @throws CustomException ROOM_NOT_FOUND - 방이 존재하지 않음
404+ * @throws CustomException ROOM_FORBIDDEN - 비공개 방에 대한 접근 권한 없음
391405 */
392406 public List <RoomMemberResponse > getOnlineMembersWithWebSocket (Long roomId , Long userId ) {
393407
@@ -402,21 +416,31 @@ public List<RoomMemberResponse> getOnlineMembersWithWebSocket(Long roomId, Long
402416 }
403417
404418 try {
405- // DB에서 모든 멤버 조회
419+ // DB에서 모든 온라인 멤버 조회
406420 List <RoomMember > allMembers = roomMemberRepository .findOnlineMembersByRoomId (roomId );
407421
408422 // WebSocket에서 실제 온라인 상태 조회
409423 Set <Long > webSocketOnlineUsers = sessionManager .getOnlineUsersInRoom (roomId );
410424
411425 // 두 정보를 결합하여 정확한 온라인 상태 반영
412- return allMembers .stream ()
426+ List < RoomMemberResponse > onlineMembers = allMembers .stream ()
413427 .filter (member -> webSocketOnlineUsers .contains (member .getUser ().getId ()))
414428 .map (RoomMemberResponse ::from )
415429 .collect (Collectors .toList ());
416430
431+ log .debug ("WebSocket 기반 온라인 멤버 조회 성공 - 방: {}, DB: {}명, WebSocket: {}명, 실제 온라인: {}명" ,
432+ roomId , allMembers .size (), webSocketOnlineUsers .size (), onlineMembers .size ());
433+
434+ return onlineMembers ;
435+
436+ } catch (CustomException e ) {
437+ // CustomException은 다시 던져서 상위에서 처리
438+ throw e ;
439+
417440 } catch (Exception e ) {
418- log .warn ("WebSocket 기반 멤버 목록 조회 실패, DB 정보만 사용 - 방: {}" , roomId , e );
419- // WebSocket 연동 실패 시 기존 방식으로 폴백
441+ log .warn ("WebSocket 연동 실패하여 DB 정보만 사용 - 방: {}, 오류: {}" , roomId , e .getMessage ());
442+
443+ // WebSocket 연동 실패 시 기존 방식으로 폴백 (DB 정보만 사용)
420444 return roomMemberRepository .findOnlineMembersByRoomId (roomId ).stream ()
421445 .map (RoomMemberResponse ::from )
422446 .collect (Collectors .toList ());
0 commit comments