배경
v4 회의실은 기능은 v3 동등까지 왔지만, 컨트롤이 여러 곳에 흩어져 있었습니다. 레이아웃 모드(기본/발표자/발언자/세미나)와 공유 카테고리는 헤더 중앙 토글에, 회의 옵션은 우측 슬라이드 사이드바에, 기기 전환은 전체 설정 다이얼로그 깊숙이 있었습니다. 초대 링크로 처음 들어오는 사람은 닉네임 페이지와 장치설정 페이지를 차례로 거쳐야 했고, 회의 중 새로고침하면 로비로 튕겨 방을 잃었습니다.
문서공유 모드는 상단에 122px 비디오 스트립이 상시 고정돼 문서 세로 공간을 계속 잡아먹고 있었습니다. 사용자들이 익숙한 레퍼런스는 Google Meet였고, 목표는 그 수준의 “컨트롤이 있어야 할 자리에 있는” 회의실이었습니다.
접근
먼저 재사용 앵커 메뉴 킷부터 만들었습니다. 기존 모드 팝오버에서 검증된 로직 — 포털, 트리거 기준 위치계산(footer에서 위로 열림), focus-trap, Esc·외부클릭 닫기, ↑↓/Home/End 키보드 탐색, menu role — 을 일반화해 공용 프리미티브로 뽑았습니다. 이후 공유 메뉴·회의 옵션·보기 조정·마이크/카메라 기기 선택이 모두 이 킷 위에서 만들어졌습니다.
그 위에서 컨트롤을 재배치했습니다. footer 공유 버튼 하나를 누르면 [화면 공유 / 문서 공유 / 공용 노트 / VOD]가 위로 열리고, 화면공유 미지원 기기(iOS)에선 그 항목만 비활성화해 문서 공유는 계속 쓸 수 있게 했습니다. 우측 사이드바였던 회의 옵션은 footer ⋯ 버튼 위 앵커 드롭다운으로 바꾸고, 상단에 ‘보기 조정’ 섹션을 둬 레이아웃 모드를 옮겼습니다. 덕분에 헤더 중앙 토글 2종을 걷어내 미니멀 헤더가 됐습니다. 마이크/카메라 버튼 옆 chevron은 전체 설정 없이 기기·스피커를 즉시 전환하고, 음성 변조와 배경 효과도 그 가로 바로 들어갔습니다.
컨테이너만 교체하고 항목·콜백·호스트 게이팅은 그대로 둔 덕분에 기존 테스트를 유지한 채 UI 구조를 크게 바꿀 수 있었습니다.
입장 플로우는 pre-join 한 페이지로 합쳤습니다. 권한이 없으면 Permissions API로 판정해 “참여자들이 나를 보고 듣도록 하시겠습니까?” 모달을 먼저 띄우고(동시/개별/없이 계속), 이후 한 화면에 16:9 프리뷰·원형 토글·기기 chip·이름 입력·[참여]를 배치했습니다. 초대 링크와 로비 모두 이 페이지로 직행하고, 닉네임 커밋과 게스트 로그인은 [참여] 시점으로 옮겼습니다. 영향받은 e2e 21개 스펙은 새 셀렉터로 일괄 갱신했습니다. 새로고침 재입장은 방 정보를 sessionStorage에 두어, 같은 탭 새로고침은 1클릭 재입장하고 새 탭에 URL을 붙여넣었을 땐 이전 방에 들어가지 않도록 구분했습니다.
문서공유의 고정 스트립은 드래그 PiP로 바꿨습니다. 단, 문서공유 모드에선 이 비디오 그리드가 원격 트랙 수신 해상도를 통지하는 유일한 주체라 “제거”하면 영상이 끊깁니다. 그래서 같은 props로 계속 mount한 채 위치만 floating 카드로 옮겼고, 브라우저 네이티브 PiP는 단일 video만 담을 수 있어 다중 참가자 그리드엔 맞지 않아 앱 내 방식을 택했습니다. 문서 뷰어엔 방향키·PageUp/Down·휠·트랙패드 페이지 이동(누적 임계 + 쿨다운으로 관성 다중 넘김 방지), 페이지 썸네일, 업로드 전 확장자 검증을 더했습니다.
마지막으로 옵션 탭 첫 클릭이 느린 문제를 Playwright로 계측(보안 탭 1,026ms, 초대 330ms)하고, 회의실이 안정된 뒤 requestIdleCallback으로 sub-panel lazy 청크 23종을 백그라운드 prefetch, 아직 로딩 중이면 스켈레톤을 즉시 보여주도록 했습니다. 배경 클릭으로 옵션을 닫은 뒤 탭이 다시 안 열리던 버그는 두 번의 추정 수정이 빗나간 뒤 실브라우저 재현·계측으로 원인(sub-panel open 상태 미리셋)을 확정해 한 곳에서 일괄 리셋했습니다.
결과
- 초대 링크 → 회의실 입장 전 페이지 2 → 1 (권한 모달 + 통합 pre-join), 새로고침 시 같은 방 1클릭 재입장.
- 문서공유 상시 비디오 스트립 122px → 0, 드래그 PiP로 이동 — 수신 해상도 통지 계약 유지.
- 앵커 메뉴 킷 1개로 공유·옵션·보기 조정·기기 전환 통합, 헤더 중앙 토글 2종 제거.
- 옵션 sub-panel lazy 청크 23종 idle prefetch + 스켈레톤 — 첫 진입 최대 1,026ms 지연 완화.
- 문서 뷰어 키보드·휠·트랙패드 페이지 이동(신규), 썸네일 복원, 미지원 포맷 조기 차단.
- 3일 동안 단위 테스트 2,488 → 2,554, e2e 21개 스펙을 새 pre-join 플로우로 갱신.
배운 점
UI 재배치에서 가장 조심했던 건 “보이는 걸 옮기다가 보이지 않는 계약을 끊는 것”이었습니다. 문서공유 비디오 스트립은 화면상으론 장식 같았지만 실제론 영상 수신 품질을 결정하는 주체였고, 그걸 모르고 지웠다면 문서공유 중 모든 참가자 영상이 저화질로 떨어졌을 겁니다. 옮기기 전에 그 컴포넌트가 무엇을 책임지는지 먼저 분석하는 단계를 생략하지 않게 됐습니다.
또, 사용자 피드백에 따라 슬라이드 애니메이션·채팅 프리뷰 토스트처럼 만들었다가 되돌린 것도 있었습니다. 공통 킷 위에서 만들었기 때문에 되돌리는 비용이 작았고, 그래서 레퍼런스와 실제 사용감 사이에서 빠르게 여러 번 시도해볼 수 있었습니다.