문제
StatusTracker.GetUserStatus는 전송 계층 실패 시 WDebug.LogError 후 yield break로 빠져나가면서 handler를 전혀 호출하지 않는다. MatchStatusPoller는 StartCoroutine 직전에 _waiting = true로 걸어두고 이 값을 HandleStatus에서만 해제하므로, 핸들러가 호출되지 않으면 _waiting이 영원히 true로 남는다. 이후 모든 Update()가 조기 return 되어 폴링이 완전히 죽는다. 같은 코루틴의 파싱/빈 상태 분기(61-66행)는 yield return handler.Invoke(null)을 제대로 호출하고 있어, 이는 의도된 설계가 아니라 분기 간 불일치다.
위치
client/Assets/Scripts/LobbyScene/StatusTracker.cs:49
재현 / 영향
플레이어가 큐에 들어가면 poller가 2초마다 GET /api/users/mine/status를 호출한다. 이 중 한 번이 전송 계층에서 실패하면(인그레스 502, 요청 타임아웃, 짧은 Wi-Fi 끊김, WebGL 네트워크/CORS 오류) www.result != Success → 로그 → yield break로 끝나고 HandleStatus가 실행되지 않아 _waiting이 true로 고정된다. 이후 서버가 매칭을 성사시켜 상태를 OnPlaying으로 바꿔도 클라이언트는 이를 관측하지 못한다. 로비는 계속 Matching UI를 표시하고, OnMatched가 발생하지 않으며, RecoverGameSession도 호출되지 않아 GameScene이 로드되지 않는다. 결과적으로 서버에서 이미 시작된 매치를 플레이어가 그대로 몰수당한다. 로비의 다른 경로로는 복구되지 않는다 — LobbyUIController.cs:95는 씬 로드 시 GetUserStatus를 단 한 번만 호출하는 일회성 경로다.
수정 방향
StatusTracker.GetUserStatus의 49행 yield break를 yield return handler.Invoke(null); yield break;로 바꿔 전송 실패 경로가 64행의 빈 상태 경로와 동일하게 동작하도록 한다. 공용 코루틴에서 고치면 두 호출자 모두 커버된다. 추가로 MatchStatusPoller가 래퍼 코루틴(yield return inner; _waiting = false;)에서 _waiting을 해제하도록 바꾸면 이후 어떤 조기 종료가 생겨도 다시 잠기지 않는다.
심각도: high · 분류: correctness
자동 코드 리뷰(멀티 에이전트 검증 통과)에서 발견됨.
문제
StatusTracker.GetUserStatus는 전송 계층 실패 시WDebug.LogError후yield break로 빠져나가면서handler를 전혀 호출하지 않는다.MatchStatusPoller는StartCoroutine직전에_waiting = true로 걸어두고 이 값을HandleStatus에서만 해제하므로, 핸들러가 호출되지 않으면_waiting이 영원히 true로 남는다. 이후 모든Update()가 조기 return 되어 폴링이 완전히 죽는다. 같은 코루틴의 파싱/빈 상태 분기(61-66행)는yield return handler.Invoke(null)을 제대로 호출하고 있어, 이는 의도된 설계가 아니라 분기 간 불일치다.위치
client/Assets/Scripts/LobbyScene/StatusTracker.cs:49재현 / 영향
플레이어가 큐에 들어가면 poller가 2초마다
GET /api/users/mine/status를 호출한다. 이 중 한 번이 전송 계층에서 실패하면(인그레스 502, 요청 타임아웃, 짧은 Wi-Fi 끊김, WebGL 네트워크/CORS 오류)www.result != Success→ 로그 →yield break로 끝나고HandleStatus가 실행되지 않아_waiting이 true로 고정된다. 이후 서버가 매칭을 성사시켜 상태를OnPlaying으로 바꿔도 클라이언트는 이를 관측하지 못한다. 로비는 계속 Matching UI를 표시하고,OnMatched가 발생하지 않으며,RecoverGameSession도 호출되지 않아 GameScene이 로드되지 않는다. 결과적으로 서버에서 이미 시작된 매치를 플레이어가 그대로 몰수당한다. 로비의 다른 경로로는 복구되지 않는다 —LobbyUIController.cs:95는 씬 로드 시GetUserStatus를 단 한 번만 호출하는 일회성 경로다.수정 방향
StatusTracker.GetUserStatus의 49행yield break를yield return handler.Invoke(null); yield break;로 바꿔 전송 실패 경로가 64행의 빈 상태 경로와 동일하게 동작하도록 한다. 공용 코루틴에서 고치면 두 호출자 모두 커버된다. 추가로MatchStatusPoller가 래퍼 코루틴(yield return inner; _waiting = false;)에서_waiting을 해제하도록 바꾸면 이후 어떤 조기 종료가 생겨도 다시 잠기지 않는다.심각도: high · 분류: correctness
자동 코드 리뷰(멀티 에이전트 검증 통과)에서 발견됨.