처음에는 WebSocket 접속 시 클라이언트의 고유 ID를 식별하기 위해 determineUser() 메서드에서 다음과 같이 UUID를 반환하는 방식으로 구현했다.
return () -> UUID.randomUUID().toString();
처음에는 이 방식으로도 충분할 것이라고 생각했다. UUID는 고유하고 충돌이 없기 때문에, 각 클라이언트 접속을 고유하게 식별할 수 있다고 보았기 때문이다.
하지만 실제 테스트 중 예상치 못한 문제가 발생했다. 클라이언트가 한 번 WebSocket에 연결할 때, determineUser()가 한 번만 호출되지 않고 여러 번 호출되는 현상이 있었고, 그 결과 매 호출 시마다 서로 다른 UUID가 생성되어 같은 사용자임에도 서로 다른 세션 ID로 처리되는 문제가 발생했다.
로그를 통해 확인해보니, determineUser()는 핸드셰이크 과정 중에 조건에 따라 여러 번 호출될 수 있으며, 이 중 일부는 ServletServerHttpRequest를 기반으로 하지 않아 HTTP 세션 정보를 얻지 못하는 경우가 있었다. 이 때 UUID를 새로 생성하는 fallback 로직이 동작하게 되며, 결국 한 사용자가 여러 명으로 인식되는 현상이 생긴 것이다.
D1E7AAF2225DCAA33695177EB50FDAED
D1E7AAF2225DCAA33695177EB50FDAED
D1E7AAF2225DCAA33695177EB50FDAED
이 문제를 해결하기 위해, HTTP 세션이 존재하는 경우에는 세션 ID를 고정적으로 반환하고, 없는 경우는 연결을 제한하거나 로그를 통해 추적하는 방식으로 수정하였다. 핵심은 동일한 사용자에게는 항상 동일한 세션 ID가 할당되도록 하는 것이며, 이를 위해 HttpSession에서 얻은 ID를 사용해야 한다는 결론에 도달했다.
즉, UUID 기반의 동적 생성 방식은 Spring WebSocket의 복잡한 핸드셰이크 로직 하에서는 예측 불가능한 결과를 초래할 수 있으므로, 가능한 경우에는 고정된 세션 기반 식별자를 사용하는 것이 안정적인 설계임을 알 수 있었다.