Files

7.1 KiB

PRD: 라이브룸 전역 표시와 키보드 레이아웃 수정

1. Overview

라이브룸 표시 계층을 메인 페이지 내부에서 앱 최상위 계층으로 옮겨 현재 화면과 무관하게 입장 결과가 보이도록 하고, 종료 후 입장 전 화면을 복원하며, 라이브 채팅 키보드 표시 시 중복 레이아웃 이동을 제거한다.

2. Problem

  • LiveViewModel.enterRoom(roomId:) 성공 후 AppState.shared.isShowPlayertrue가 되어도 LiveRoomViewV2MainView 내부에만 배치되어 있다.
  • 크리에이터 채널과 라이브 생성 화면은 ContentViewNavigationStack destination으로 메인 페이지 위에 표시되므로, 라이브룸 상태가 활성화되어도 현재 destination보다 아래에서 렌더링될 수 있다.
  • LiveRoomViewV2는 채팅 키보드 높이만큼 콘텐츠를 수동으로 올리지만, 화면 캡처 보호용 ScreenCaptureSecureContainer가 SwiftUI와 내부 UIHostingController 사이에 경계를 만든다.
  • 바깥 SwiftUI 계층의 키보드 safe area만 무시해도 내부 UIHostingController의 기본 safeAreaRegions == .all에 키보드 영역이 남는다. 내부 콘텐츠가 자동으로 줄어든 뒤 수동 offset까지 적용되어 키보드 위에 불필요한 빈 공간이 생긴다.
  • ScreenCaptureSecureContainer 자체가 일반 container safe area 안에 배치되면 내부 배경의 edgesIgnoringSafeArea가 UIKit 컨테이너 경계를 넘어갈 수 없어 라이브룸이 화면 전체를 덮지 못한다.
  • 공용 enterRoom 성공 처리에서 setAppStep(.main)을 호출해 모든 일반 입장 경로의 navigation path를 삭제한다. 라이브 종료는 전역 overlay만 숨기므로 홈, 라이브 상세, 크리에이터 채널, 프로필 등 입장 전 화면 대신 메인 페이지가 나타난다.

3. Goals

  • 어떤 NavigationStack destination이 표시 중이어도 라이브룸 입장 성공 시 LiveRoomViewV2가 앱 화면 최상위에 표시된다.
  • 라이브룸의 보안 컨테이너와 배경이 상단 및 하단 safe area를 포함한 화면 전체를 덮는다.
  • 크리에이터 채널에서 즉시 시작 라이브를 생성하면 enterRoom 성공 직후 라이브룸이 보인다.
  • 라이브룸 표시 계층 변경 후에도 라이브 중 푸시/딥링크 외부 이동 확인 다이얼로그가 라이브룸 위에 표시된다.
  • 채팅 키보드가 표시될 때 입력창은 키보드 바로 위에 위치하고, 키보드 높이만큼의 중복 빈 공간이 생기지 않는다.
  • 앱 내부의 일반 입장에서는 현재 navigation path를 보존하고, 라이브 종료 후 입장 직전 화면을 다시 표시한다.
  • 콜드 스타트 라이브 푸시는 스플래시 처리 지점에서 메인 페이지를 준비한 뒤 정상적으로 입장한다.
  • 기존 입장 API, Agora 초기화/종료, 채팅 전송, 캡처 보호 동작을 유지한다.

4. Non-Goals

  • enterRoom, getRoomDetail, 결제 또는 비밀번호 확인의 API 요청·응답 처리 흐름을 변경하지 않는다.
  • 라이브 생성 후 메인/홈/라이브 데이터 갱신 정책을 변경하지 않는다.
  • 라이브룸 UI 디자인이나 채팅 컴포넌트 모양을 변경하지 않는다.
  • 키보드 처리 공통 모듈 전체를 리팩터링하지 않는다.
  • Pods/**, generated/**, build/**를 수정하지 않는다.

5. Core Requirements

5.1 라이브룸 전역 표시

  • LiveRoomViewV2의 단일 표시 지점을 MainView 내부가 아닌 ContentViewNavigationStack 최상위 overlay로 이동한다.
  • 표시 조건은 기존과 동일하게 AppState.shared.isShowPlayer를 사용한다.
  • LiveRoomViewV2를 중복 생성하지 않는다.
  • LiveViewModel.enterRoom(roomId:)의 API 성공 판정과 AppState.shared.roomId 설정은 변경하지 않는다.

5.2 외부 이동 확인 보존

  • 라이브 중 푸시/딥링크 이동 요청의 pending action을 앱 최상위 계층에서 접근 가능한 상태로 관리한다.
  • 확인 다이얼로그는 전역 라이브룸보다 위에 표시한다.
  • 확인 시 기존과 같이 .requestLiveRoomQuitForExternalNavigation 알림으로 라이브 종료를 요청하고, isShowPlayer == false가 된 뒤 pending action을 실행한다.
  • 취소 시 pending action과 cancel action을 정리하고 라이브룸을 유지한다.

5.3 키보드 레이아웃

  • 기존 수동 appliedKeyboardHeight offset 동작은 유지한다.
  • ScreenCaptureSecureContainer는 화면 전체 크기로 확장하고 바깥 SwiftUI 계층의 safe area를 무시한다.
  • 내부 UIHostingController.safeAreaRegions.container로 제한해 일반 화면 safe area는 전달하되 키보드 safe area는 전달하지 않는다.
  • 시스템 키보드 회피와 수동 offset이 동시에 적용되지 않도록 한다.
  • 캡처 보호 활성/비활성 상태 모두 같은 키보드 레이아웃 규칙을 사용한다.

5.4 입장 전 화면 복원

  • 공용 LiveViewModel.enterRoomUserProfileViewModel.enterRoom은 라이브 상태만 활성화하고 navigation을 변경하지 않는다.
  • 홈, 라이브 탭, 라이브 상세, 크리에이터 채널, 프로필 등 앱 내부 진입점은 각각의 현재 화면을 라이브룸 아래에 유지한다.
  • 콜드 스타트 라이브 푸시는 SplashView에서 pushRoomId를 소비하고 .main을 설정한 뒤 입장한다.
  • 포그라운드 푸시와 딥링크의 기존 호출부별 navigation 정책은 유지한다.

6. Technical Constraints

  • 변경은 라이브룸 전역 표시, 키보드 레이아웃, 공용 입장 성공 처리와 콜드 스타트 푸시 처리에 직접 관련된 기존 파일에 한정한다.
  • 기존 SodaV2ActionModal과 외부 이동 확인 문구를 재사용한다.
  • 신규 사용자 노출 문자열이나 신규 API를 추가하지 않는다.
  • 자동화 테스트 번들 타깃이 없는 현재 프로젝트 구성에서는 정적 검색과 SodaLive-dev Debug 빌드로 자동 검증하고, 실제 키보드 높이는 수동 QA 항목으로 남긴다.

7. Success Criteria

  • 크리에이터 채널에서 즉시 라이브 생성 후 라이브룸이 현재 destination 위에 표시된다.
  • 홈, 라이브, 크리에이터 채널 등 진입 화면과 무관하게 isShowPlayer == true이면 전역 라이브룸이 한 번만 표시된다.
  • 라이브룸 배경이 상태 표시줄과 홈 인디케이터 영역을 포함한 화면 전체를 덮는다.
  • 라이브 중 외부 이동 요청 시 확인 다이얼로그가 라이브룸 위에 표시되고 확인/취소가 기존 의미대로 동작한다.
  • 채팅 입력 포커스 시 화면 이동량이 키보드 회피와 중복되지 않으며 입력창 아래에 큰 빈 공간이 생기지 않는다.
  • 앱 내부에서 라이브 종료 시 입장 직전 화면과 navigation path가 유지된다.
  • 콜드 스타트 라이브 푸시에서는 스플래시가 사라지고 메인 페이지 위에 라이브룸이 표시된다.
  • xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build가 성공한다.

8. Open Questions

  • 해당 없음.