Skip to content

[Refactor] RTC SSE·Socket.IO·LiveKit 실시간 통신 역할 재검증 #44

Description

@lioba00700

🎯 목표

RTC에서 사용하는 LiveKit, SSE, Socket.IO의 역할과 경계를 재검증한다.

각 Transport의 책임, 연결 상태 및 종료 시점의 상호작용을 확인하고 실시간 통신 구조의 개선 필요 여부를 판단한다.

🔍 범위

  • LiveKit
  • SSE
  • Socket.IO
  • Room / Participant 상태
  • Viewer Reaction
  • RTC 종료 / 재연결

✅ 완료 조건

  • 각 Transport의 책임과 데이터 범위 확인
  • Room / Participant 상태 변화 흐름 검증
  • Viewer Reaction 전송 경로 확인
  • RTC 종료 시 Transport 간 경쟁 조건 검토
  • 연결 끊김 및 재연결 정책 확인
  • 구조적 문제 및 리팩토링 필요 여부 판단
  • 필요한 Architecture / ADR 문서 갱신

Activity

  1. self-assigned this
    on Aug 8, 2026
  2. lioba00700 commented on Sep 5, 2026

    @lioba00700
    MemberAuthor

    SSE 재연결 정책에서 인증 만료(401) 복구 경로가 빠져 있음.

    현재 subscribeRtcRoomEvents는 구독 시점의 access token을 직접 읽어 expo/fetch로 SSE 요청을 보내고, non-2xx 응답은 상태 구분 없이 에러로 처리함. Host/Viewer 쪽에서는 해당 에러를 받아 backoff 후 재구독만 수행하며 refreshAuthSession()을 호출하는 경로가 없음.

    일반 Axios 요청과 upload fetch는 401 발생 시 access token refresh 후 재요청하지만, SSE는 이 경로를 거치지 않음. 재구독할 때 store의 최신 access token을 다시 읽기는 하므로 다른 API 요청이 먼저 refresh를 수행한 경우 간접 복구될 수 있으나, SSE 요청만 유지되는 상황에서는 만료 토큰으로 401 재연결을 반복할 수 있음.

    SSE가 RTC Room 상태를 유지하는 핵심 채널인 만큼 401 발생 시 자체적으로 인증 세션을 복구한 뒤 재구독할 수 있도록 처리 필요.

  3. lioba00700 commented on Sep 5, 2026

    @lioba00700
    MemberAuthor

    LiveKit 재연결 책임은 Host와 Viewer가 다르게 가져가고 있음.

    Viewer는 LiveKitRoom 컴포넌트를 통해 연결/재연결 책임을 SDK에 주로 위임하고, 앱 코드에서는 연결 오류를 UI 상태로 노출하는 정도로 처리함.

    반면 Host는 LiveKit Room 연결 외에 Camera Publisher/Track lifecycle까지 함께 맞춰야 하므로 앱 레벨에서 추가 orchestration을 수행함. connectPromiseRef로 중복 connect를 방지하고, lifecycleEpochRef로 이전 연결 완료가 최신 상태를 덮지 않도록 보호하며, cleanupPromiseRef로 정리 작업을 직렬화함. 필요 시 ensureConnected()를 통해 연결을 다시 보장하는 구조임.

    Host가 SDK 기본 재연결만 사용하지 않는 이유는 Room 연결 상태뿐 아니라 카메라 publish/stop, 화면 focus/active 상태, 종료 시 publisher 정리와 disconnect 순서까지 함께 일관되게 관리해야 하기 때문으로 보임. 따라서 Host/Viewer 간 재연결 전략 차이는 현재 역할 차이에 따른 의도된 설계로 판단됨.

  4. lioba00700 commented on Sep 5, 2026

    @lioba00700
    MemberAuthor

    RTC 종료 경쟁 조건은 endRoom() -> LiveKit 결과 RPC -> disconnectRoom() 순서와 Viewer의 SSE ended -> connection=null -> LiveKit unmount 흐름이 겹치면서 발생할 수 있음.

    서버 endRoom() 처리 직후 SSE ended가 Viewer에 먼저 도착하면 Viewer의 LiveKit RPC handler가 제거된 뒤 Host가 결과 RPC를 호출할 수 있어, RPC 성공 여부가 네트워크 타이밍에 의존하게 됨.

    현재 Viewer는 RPC를 받지 못하더라도 ROOM_ENDED fallback 이후 저장된 사진을 HTTP로 다시 조회할 수 있으므로, 수정 방향은 서버 endRoom() 성공을 RTC 종료의 기준으로 두고 결과 RPC는 best-effort 전달 경로로 낮추는 방향이 적절해 보임. 즉 RPC 실패를 Host 종료 전체 실패로 취급하지 않고 cleanup/disconnect는 그대로 완료하도록 처리.

    이렇게 하면 race 자체는 남아도 기능 실패로 이어지지 않음. 다만 구현 전 아래 보장 여부는 확인 필요:

    • endRoom() 성공 시 결과 사진이 서버에 이미 저장되어 있어 Viewer HTTP fallback이 항상 가능할 것
    • LIVE 진입 이력이 있는 Viewer가 SSE ended를 받았을 때 결과 화면 fallback으로 반드시 전환될 것
    • RPC 실패 여부와 관계없이 Host disconnectRoom()과 세션 정리가 항상 실행될 것
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions