33import com .back .global .exception .CustomException ;
44import com .back .global .exception .ErrorCode ;
55import com .back .global .websocket .dto .WebSocketSessionInfo ;
6+ import com .fasterxml .jackson .databind .DeserializationFeature ;
7+ import com .fasterxml .jackson .databind .ObjectMapper ;
8+ import com .fasterxml .jackson .datatype .jsr310 .JavaTimeModule ;
69import lombok .RequiredArgsConstructor ;
710import lombok .extern .slf4j .Slf4j ;
811import org .springframework .data .redis .core .RedisTemplate ;
912import org .springframework .stereotype .Service ;
1013
1114import java .time .Duration ;
15+ import java .util .LinkedHashMap ;
1216import java .util .Set ;
1317import java .util .stream .Collectors ;
1418
@@ -24,7 +28,7 @@ public class WebSocketSessionManager {
2428 private static final String SESSION_USER_KEY = "ws:session:{}" ;
2529 private static final String ROOM_USERS_KEY = "ws:room:{}:users" ;
2630
27- // TTL 설정 (10분) - Heartbeat와 함께 사용하여 정확한 상태 관리
31+ // TTL 설정 (10분)
2832 private static final int SESSION_TTL_MINUTES = 10 ;
2933
3034 // 사용자 세션 추가 (연결 시 호출)
@@ -70,7 +74,22 @@ public boolean isUserConnected(Long userId) {
7074 public WebSocketSessionInfo getSessionInfo (Long userId ) {
7175 try {
7276 String userKey = USER_SESSION_KEY .replace ("{}" , userId .toString ());
73- return (WebSocketSessionInfo ) redisTemplate .opsForValue ().get (userKey );
77+ Object value = redisTemplate .opsForValue ().get (userKey );
78+
79+ if (value == null ) {
80+ return null ;
81+ }
82+
83+ // LinkedHashMap으로 역직렬화된 경우 또는 타입이 맞지 않는 경우 변환
84+ if (value instanceof LinkedHashMap || !(value instanceof WebSocketSessionInfo )) {
85+ ObjectMapper mapper = new ObjectMapper ();
86+ mapper .registerModule (new JavaTimeModule ());
87+ mapper .configure (DeserializationFeature .FAIL_ON_UNKNOWN_PROPERTIES , false );
88+ return mapper .convertValue (value , WebSocketSessionInfo .class );
89+ }
90+
91+ return (WebSocketSessionInfo ) value ;
92+
7493 } catch (Exception e ) {
7594 log .error ("세션 정보 조회 실패 - 사용자: {}" , userId , e );
7695 throw new CustomException (ErrorCode .WS_REDIS_ERROR );
@@ -106,7 +125,6 @@ public void updateLastActivity(Long userId) {
106125 log .warn ("세션 정보가 없어 활동 시간 업데이트 실패 - 사용자: {}" , userId );
107126 }
108127 } catch (CustomException e ) {
109- // 이미 처리된 CustomException은 다시 던짐
110128 throw e ;
111129 } catch (Exception e ) {
112130 log .error ("사용자 활동 시간 업데이트 실패 - 사용자: {}" , userId , e );
@@ -192,7 +210,7 @@ public Set<Long> getOnlineUsersInRoom(Long roomId) {
192210
193211 if (userIds != null ) {
194212 return userIds .stream ()
195- .map (obj -> ( Long ) obj )
213+ .map (this :: convertToLong ) // 안전한 변환
196214 .collect (Collectors .toSet ());
197215 }
198216 return Set .of ();
@@ -220,16 +238,17 @@ public Long getUserCurrentRoomId(Long userId) {
220238 return sessionInfo != null ? sessionInfo .currentRoomId () : null ;
221239 } catch (CustomException e ) {
222240 log .error ("사용자 현재 방 조회 실패 - 사용자: {}" , userId , e );
223- return null ; // 조회용이므로 예외 대신 null 반환
241+ return null ;
224242 }
225243 }
226244
227245 // 내부적으로 세션 제거 처리
228246 private void removeSessionInternal (String sessionId ) {
229247 String sessionKey = SESSION_USER_KEY .replace ("{}" , sessionId );
230- Long userId = ( Long ) redisTemplate .opsForValue ().get (sessionKey );
248+ Object userIdObj = redisTemplate .opsForValue ().get (sessionKey );
231249
232- if (userId != null ) {
250+ if (userIdObj != null ) {
251+ Long userId = convertToLong (userIdObj ); // 안전한 변환
233252 WebSocketSessionInfo sessionInfo = getSessionInfo (userId );
234253
235254 // 방에서 퇴장 처리
@@ -243,4 +262,15 @@ private void removeSessionInternal(String sessionId) {
243262 redisTemplate .delete (sessionKey );
244263 }
245264 }
265+
266+ // Object를 Long으로 안전하게 변환하는 헬퍼 메서드
267+ private Long convertToLong (Object obj ) {
268+ if (obj instanceof Long ) {
269+ return (Long ) obj ;
270+ } else if (obj instanceof Number ) {
271+ return ((Number ) obj ).longValue ();
272+ } else {
273+ throw new IllegalArgumentException ("Cannot convert " + obj .getClass () + " to Long" );
274+ }
275+ }
246276}
0 commit comments