Skip to content

Commit 6555f5f

Browse files
committed
Refactor: WebSocketSessionManager에서 RoomParticipantService 분리
1 parent 3c55518 commit 6555f5f

File tree

2 files changed

+175
-80
lines changed

2 files changed

+175
-80
lines changed
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
package com.back.global.websocket.service;
2+
3+
import com.back.global.exception.CustomException;
4+
import com.back.global.exception.ErrorCode;
5+
import com.back.global.websocket.dto.WebSocketSessionInfo;
6+
import com.back.global.websocket.store.RedisSessionStore;
7+
import lombok.RequiredArgsConstructor;
8+
import lombok.extern.slf4j.Slf4j;
9+
import org.springframework.stereotype.Service;
10+
11+
import java.util.Set;
12+
13+
/**
14+
* 방 참가자 관리 서비스
15+
* - 방 입장/퇴장 처리
16+
* - 방별 참가자 목록 관리
17+
* - 방별 온라인 사용자 통계
18+
*/
19+
@Slf4j
20+
@Service
21+
@RequiredArgsConstructor
22+
public class RoomParticipantService {
23+
24+
private final RedisSessionStore redisSessionStore;
25+
26+
// 사용자 방 입장
27+
public void enterRoom(Long userId, Long roomId) {
28+
try {
29+
WebSocketSessionInfo sessionInfo = redisSessionStore.getUserSession(userId);
30+
31+
if (sessionInfo == null) {
32+
log.warn("세션 정보가 없어 방 입장 실패 - 사용자: {}, 방: {}", userId, roomId);
33+
throw new CustomException(ErrorCode.WS_SESSION_NOT_FOUND);
34+
}
35+
36+
// 기존 방에서 퇴장 처리
37+
if (sessionInfo.currentRoomId() != null) {
38+
exitRoom(userId, sessionInfo.currentRoomId());
39+
log.debug("기존 방에서 퇴장 처리 완료 - 사용자: {}, 이전 방: {}",
40+
userId, sessionInfo.currentRoomId());
41+
}
42+
43+
// 세션 정보에 방 ID 업데이트
44+
WebSocketSessionInfo updatedSession = sessionInfo.withRoomId(roomId);
45+
redisSessionStore.saveUserSession(userId, updatedSession);
46+
47+
// 방 참가자 목록에 추가
48+
redisSessionStore.addUserToRoom(roomId, userId);
49+
50+
log.info("방 입장 완료 - 사용자: {}, 방: {}", userId, roomId);
51+
52+
} catch (CustomException e) {
53+
throw e;
54+
} catch (Exception e) {
55+
log.error("방 입장 실패 - 사용자: {}, 방: {}", userId, roomId, e);
56+
throw new CustomException(ErrorCode.WS_ROOM_JOIN_FAILED);
57+
}
58+
}
59+
60+
// 사용자 방 퇴장
61+
public void exitRoom(Long userId, Long roomId) {
62+
try {
63+
WebSocketSessionInfo sessionInfo = redisSessionStore.getUserSession(userId);
64+
65+
if (sessionInfo == null) {
66+
log.warn("세션 정보가 없지만 방 퇴장 처리 계속 진행 - 사용자: {}, 방: {}", userId, roomId);
67+
} else {
68+
// 세션 정보에서 방 ID 제거
69+
WebSocketSessionInfo updatedSession = sessionInfo.withoutRoom();
70+
redisSessionStore.saveUserSession(userId, updatedSession);
71+
}
72+
73+
// 방 참가자 목록에서 제거
74+
redisSessionStore.removeUserFromRoom(roomId, userId);
75+
76+
log.info("방 퇴장 완료 - 사용자: {}, 방: {}", userId, roomId);
77+
78+
} catch (Exception e) {
79+
log.error("방 퇴장 실패 - 사용자: {}, 방: {}", userId, roomId, e);
80+
throw new CustomException(ErrorCode.WS_ROOM_LEAVE_FAILED);
81+
}
82+
}
83+
84+
// 사용자의 현재 방 ID 조회
85+
public Long getCurrentRoomId(Long userId) {
86+
try {
87+
WebSocketSessionInfo sessionInfo = redisSessionStore.getUserSession(userId);
88+
return sessionInfo != null ? sessionInfo.currentRoomId() : null;
89+
} catch (Exception e) {
90+
log.error("사용자 현재 방 조회 실패 - 사용자: {}", userId, e);
91+
return null;
92+
}
93+
}
94+
95+
// 방의 온라인 참가자 목록 조회
96+
public Set<Long> getParticipants(Long roomId) {
97+
try {
98+
return redisSessionStore.getRoomUsers(roomId);
99+
} catch (Exception e) {
100+
log.error("방 참가자 목록 조회 실패 - 방: {}", roomId, e);
101+
throw new CustomException(ErrorCode.WS_REDIS_ERROR);
102+
}
103+
}
104+
105+
// 방의 온라인 참가자 수 조회
106+
public long getParticipantCount(Long roomId) {
107+
try {
108+
return redisSessionStore.getRoomUserCount(roomId);
109+
} catch (Exception e) {
110+
log.error("방 참가자 수 조회 실패 - 방: {}", roomId, e);
111+
throw new CustomException(ErrorCode.WS_REDIS_ERROR);
112+
}
113+
}
114+
115+
// 사용자가 특정 방에 참여 중인지 확인
116+
public boolean isUserInRoom(Long userId, Long roomId) {
117+
try {
118+
Long currentRoomId = getCurrentRoomId(userId);
119+
return currentRoomId != null && currentRoomId.equals(roomId);
120+
} catch (Exception e) {
121+
log.error("사용자 방 참여 여부 확인 실패 - 사용자: {}, 방: {}", userId, roomId, e);
122+
return false;
123+
}
124+
}
125+
126+
// 모든 방에서 사용자 퇴장 처리 (세션 종료 시 사용)
127+
public void exitAllRooms(Long userId) {
128+
try {
129+
Long currentRoomId = getCurrentRoomId(userId);
130+
131+
if (currentRoomId != null) {
132+
exitRoom(userId, currentRoomId);
133+
log.info("모든 방에서 퇴장 처리 완료 - 사용자: {}", userId);
134+
}
135+
136+
} catch (Exception e) {
137+
log.error("모든 방 퇴장 처리 실패 - 사용자: {}", userId, e);
138+
// 에러를 던지지 않고 로그만 남김 (세션 종료는 계속 진행되어야 함)
139+
}
140+
}
141+
}
Lines changed: 34 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
package com.back.global.websocket.service;
22

3-
import com.back.global.exception.CustomException;
4-
import com.back.global.exception.ErrorCode;
53
import com.back.global.websocket.dto.WebSocketSessionInfo;
6-
import com.back.global.websocket.store.RedisSessionStore;
74
import lombok.RequiredArgsConstructor;
85
import lombok.extern.slf4j.Slf4j;
96
import org.springframework.stereotype.Service;
@@ -16,32 +13,30 @@
1613
public class WebSocketSessionManager {
1714

1815
private final UserSessionService userSessionService;
19-
private final RedisSessionStore redisSessionStore;
16+
private final RoomParticipantService roomParticipantService;
2017

21-
// 사용자 세션 추가 (연결 시 호출)
18+
// ============= 세션 관리 =============
19+
20+
// 사용자 세션 추가 (WebSocket 연결 시 호출)
2221
public void addSession(Long userId, String sessionId) {
2322
userSessionService.registerSession(userId, sessionId);
23+
log.info("WebSocket 연결 완료 - 사용자: {}, 세션: {}", userId, sessionId);
2424
}
2525

26-
// 세션 제거 (연결 종료 시 호출)
26+
// 세션 제거 (WebSocket 연결 종료 시 호출)
2727
public void removeSession(String sessionId) {
28-
try {
29-
Long userId = userSessionService.getUserIdBySessionId(sessionId);
30-
31-
if (userId != null) {
32-
// 방에서 퇴장 처리
33-
Long currentRoomId = userSessionService.getCurrentRoomId(userId);
34-
if (currentRoomId != null) {
35-
leaveRoom(userId, currentRoomId);
36-
}
37-
}
38-
39-
// 세션 종료
28+
Long userId = userSessionService.getUserIdBySessionId(sessionId);
29+
30+
if (userId != null) {
31+
// 1. 모든 방에서 퇴장
32+
roomParticipantService.exitAllRooms(userId);
33+
34+
// 2. 세션 종료
4035
userSessionService.terminateSession(sessionId);
4136

42-
} catch (Exception e) {
43-
log.error("WebSocket 세션 제거 실패 - 세션: {}", sessionId, e);
44-
throw new CustomException(ErrorCode.WS_REDIS_ERROR);
37+
log.info("WebSocket 연결 종료 완료 - 세션: {}, 사용자: {}", sessionId, userId);
38+
} else {
39+
log.warn("종료할 세션을 찾을 수 없음 - 세션: {}", sessionId);
4540
}
4641
}
4742

@@ -55,89 +50,48 @@ public WebSocketSessionInfo getSessionInfo(Long userId) {
5550
return userSessionService.getSessionInfo(userId);
5651
}
5752

58-
// 사용자 활동 시간 업데이트 (Heartbeat 시 호출)
53+
// Heartbeat 처리 (활동 시간 업데이트 및 TTL 연장)
5954
public void updateLastActivity(Long userId) {
6055
userSessionService.processHeartbeat(userId);
56+
log.debug("Heartbeat 처리 완료 - 사용자: {}", userId);
6157
}
6258

6359
// 전체 온라인 사용자 수 조회
6460
public long getTotalOnlineUserCount() {
6561
return userSessionService.getTotalOnlineUserCount();
6662
}
6763

68-
// 사용자가 방에 입장 (WebSocket 전용)
64+
// ============= 방 관리 =============
65+
66+
// 사용자가 방에 입장
6967
public void joinRoom(Long userId, Long roomId) {
70-
try {
71-
WebSocketSessionInfo sessionInfo = redisSessionStore.getUserSession(userId);
72-
if (sessionInfo != null) {
73-
// 기존 방에서 퇴장
74-
if (sessionInfo.currentRoomId() != null) {
75-
leaveRoom(userId, sessionInfo.currentRoomId());
76-
}
77-
78-
// 새 방 정보 업데이트
79-
WebSocketSessionInfo updatedSessionInfo = sessionInfo.withRoomId(roomId);
80-
redisSessionStore.saveUserSession(userId, updatedSessionInfo);
81-
82-
// 방 참여자 목록에 추가
83-
redisSessionStore.addUserToRoom(roomId, userId);
84-
85-
log.info("WebSocket 방 입장 완료 - 사용자: {}, 방: {}", userId, roomId);
86-
} else {
87-
log.warn("세션 정보가 없어 방 입장 처리 실패 - 사용자: {}, 방: {}", userId, roomId);
88-
}
89-
} catch (CustomException e) {
90-
throw e;
91-
} catch (Exception e) {
92-
log.error("사용자 방 입장 실패 - 사용자: {}, 방: {}", userId, roomId, e);
93-
throw new CustomException(ErrorCode.WS_ROOM_JOIN_FAILED);
94-
}
68+
roomParticipantService.enterRoom(userId, roomId);
69+
log.info("방 입장 처리 완료 - 사용자: {}, 방: {}", userId, roomId);
9570
}
9671

97-
// 사용자가 방에서 퇴장 (WebSocket 전용)
72+
// 사용자가 방에서 퇴장
9873
public void leaveRoom(Long userId, Long roomId) {
99-
try {
100-
WebSocketSessionInfo sessionInfo = redisSessionStore.getUserSession(userId);
101-
if (sessionInfo != null) {
102-
// 방 정보 제거
103-
WebSocketSessionInfo updatedSessionInfo = sessionInfo.withoutRoom();
104-
redisSessionStore.saveUserSession(userId, updatedSessionInfo);
105-
106-
// 방 참여자 목록에서 제거
107-
redisSessionStore.removeUserFromRoom(roomId, userId);
108-
109-
log.info("WebSocket 방 퇴장 완료 - 사용자: {}, 방: {}", userId, roomId);
110-
}
111-
} catch (CustomException e) {
112-
throw e;
113-
} catch (Exception e) {
114-
log.error("사용자 방 퇴장 실패 - 사용자: {}, 방: {}", userId, roomId, e);
115-
throw new CustomException(ErrorCode.WS_ROOM_LEAVE_FAILED);
116-
}
74+
roomParticipantService.exitRoom(userId, roomId);
75+
log.info("방 퇴장 처리 완료 - 사용자: {}, 방: {}", userId, roomId);
11776
}
11877

11978
// 방의 온라인 사용자 수 조회
12079
public long getRoomOnlineUserCount(Long roomId) {
121-
try {
122-
return redisSessionStore.getRoomUserCount(roomId);
123-
} catch (Exception e) {
124-
log.error("방 온라인 사용자 수 조회 실패 - 방: {}", roomId, e);
125-
throw new CustomException(ErrorCode.WS_REDIS_ERROR);
126-
}
80+
return roomParticipantService.getParticipantCount(roomId);
12781
}
12882

12983
// 방의 온라인 사용자 목록 조회
13084
public Set<Long> getOnlineUsersInRoom(Long roomId) {
131-
try {
132-
return redisSessionStore.getRoomUsers(roomId);
133-
} catch (Exception e) {
134-
log.error("방 온라인 사용자 목록 조회 실패 - 방: {}", roomId, e);
135-
throw new CustomException(ErrorCode.WS_REDIS_ERROR);
136-
}
85+
return roomParticipantService.getParticipants(roomId);
13786
}
13887

13988
// 특정 사용자의 현재 방 조회
14089
public Long getUserCurrentRoomId(Long userId) {
141-
return userSessionService.getCurrentRoomId(userId);
90+
return roomParticipantService.getCurrentRoomId(userId);
91+
}
92+
93+
// 사용자가 특정 방에 참여 중인지 확인
94+
public boolean isUserInRoom(Long userId, Long roomId) {
95+
return roomParticipantService.isUserInRoom(userId, roomId);
14296
}
14397
}

0 commit comments

Comments
 (0)