배경

서비스는 처음부터 사용자가 하나의 탭에서 이용하는 상황을 기준으로 설계했습니다. 이에 따라 동일한 세션에서 중복 연결이 발생하는 것을 방지하기 위해 세션의 active 상태를 확인하고, 활성 세션의 수를 제한하는 방식으로 구현했습니다.

다만 브라우저에서 사용 가능한 탭을 정확히 하나로 제한하려면 탭의 생성과 종료 시점을 안정적으로 감지해야 합니다. 특히 탭이 비정상적으로 종료되거나 네트워크 연결이 끊기는 경우에는 서버가 실제 탭의 상태를 즉시 파악하기 어렵습니다. 이러한 예외 상황까지 모두 처리하려면 구현 복잡도가 크게 증가합니다.

따라서 하나의 세션에서 여러 연결을 완전히 차단하는 대신, 정상적인 사용 과정에서 발생할 수 있는 재연결과 일시적인 중복 연결을 허용하는 방향을 선택했습니다. 일반적으로는 2~3개의 연결이면 충분하다고 판단했지만, 네트워크 상태와 재연결 시점을 고려해 여유 있게 최대 5개의 활성 연결을 허용했습니다.

현재 구현 방식

현재는 서버에서 ActiveSessionRegistry를 사용해 세션별 활성 연결을 관리합니다. 새로운 연결이 생성되면 해당 세션의 활성 연결 수를 확인하고, 허용된 범위 안에서 연결을 등록합니다. 연결이 종료되면 등록된 활성 연결도 제거합니다.

이 방식은 정상적인 브라우저 사용과 SSE 재연결 상황을 처리하기 위한 최소한의 안전장치입니다. 여러 탭을 동시에 열어 사용하는 상황 자체를 완벽하게 지원하는 구조는 아니므로, 다중 탭에서 발생할 수 있는 모든 상태 불일치나 예외 동작까지 보장하지는 않습니다.

BroadcastChannel을 사용하면 동일한 브라우저 세션에 속한 모든 탭으로 상태를 전파하고, 탭 사이의 연결 상태를 동기화할 수 있습니다. 이를 통해 대표 탭 하나만 SSE 연결을 유지하거나, 세션 종료 및 상태 변경을 다른 탭에 즉시 알리는 방식도 구현할 수 있습니다.

그러나 현재 프로젝트의 일정과 요구사항을 고려하면 BroadcastChannel을 이용한 탭 간 동기화는 필요한 수준보다 복잡한 구현이라고 판단했습니다. 특히 PWA로 실행하는 경우 일반적인 브라우저 사용과 달리 여러 탭이 생성되는 상황이 드물기 때문에, 해당 기능을 추가하는 데 필요한 비용 대비 효과가 크지 않습니다. 따라서 시간 내에 안정적으로 구현할 수 있는 세션별 연결 수 제한 방식을 우선 적용했습니다.

ActiveSessionRegistry를 별도로 만든 이유

활성 연결을 관리하는 책임을 기존 세션 도메인에 직접 추가하지 않고 ActiveSessionRegistry로 분리했습니다.

SSE 기능을 작업하는 과정에서 기존 세션 도메인의 구조와 책임을 변경할 경우, SSE와 직접 관련이 없는 인증 및 세션 처리 로직까지 영향을 받을 수 있다고 판단했습니다. 제한된 작업 시간 안에서 기존 세션 도메인을 수정하고 전체 영향 범위를 검증하는 것은 부담이 컸기 때문에, 기존 코드를 최대한 건드리지 않으면서 SSE 활성 연결만 독립적으로 관리할 수 있도록 별도의 레지스트리를 도입했습니다.

현재 구조가 장기적으로 가장 이상적인 설계라고 보기는 어렵습니다. 활성 연결 관리가 세션의 생명주기와 밀접하게 연관되어 있으므로, 추후 리팩터링 시간이 확보된다면 세션 도메인과 ActiveSessionRegistry의 책임을 다시 검토할 예정입니다. 필요하다면 세션 상태와 SSE 연결 상태를 하나의 일관된 정책으로 통합하고, 다중 탭 동기화가 실제 요구사항으로 추가될 경우 BroadcastChannel 도입도 함께 고려할 수 있습니다.

현재 지원 범위

현재 구현은 하나의 탭 또는 소수의 탭에서 서비스를 사용하는 일반적인 상황과, 네트워크 문제로 인한 일시적인 SSE 재연결을 안정적으로 처리하는 것을 목표로 합니다.

최대 5개의 활성 연결을 허용하는 것은 다중 탭 사용을 공식적으로 지원한다는 의미가 아니라, 연결 종료 감지 지연이나 재연결 과정에서 정상 사용자가 차단되는 문제를 줄이기 위한 완충 장치입니다. 따라서 사용자가 의도적으로 여러 탭을 동시에 열어 사용할 때 발생하는 모든 문제를 완벽하게 처리하는 것은 현재 지원 범위에 포함되지 않습니다.