기록 목록공지사항

authenticated runtime 이전에 websocket runtime이 존재하면 안 되는 이유

humanpchumanpc ·
05-2425
최근 homepage runtime을 정리하면서 websocket 초기 연결 시점을 다시 분해했다. 처음에는 단순한 성능 문제처럼 보였다. public homepage initial load에서: * websocket chunk가 import되고 * Echo/Pusher runtime이 초기화되고 * websocket 101 연결이 발생하고 * /broadcasting/auth 요청까지 이어졌다. 그런데 실제 문제는 "몇 KB를 줄이느냐"가 아니었다. 문제는 runtime ownership이었다. [기존 구조] 초기 구조는 아래 흐름에 가까웠다. public render → datasource scan → realtime datasource 발견 → WebSocket runtime import → auth 확인 즉, public runtime 단계에서 이미 realtime runtime이 bootstrap되고 있었다. 실제 코드 흐름은: TemplateApp → DataSourceManager.subscribeWebSockets() → loadWebSocketManager() → WebSocketManager.initialize() → Echo/Pusher connect 문제는 여기서 auth_token 또는 stale user-like object만 남아 있어도 private/presence realtime 경로가 열릴 수 있었다는 점이다. 예를 들어: localStorage.auth_token 존재 또는 current_user.data.uuid 존재 같은 상태만으로 websocket runtime이 import될 수 있었다. 이건 단순 최적화 문제가 아니다. authenticated capability가 public runtime으로 누수되는 구조였다. [runtime 분리 기준] 이번 수정에서 핵심 기준은 하나였다. authenticated capability는 authenticated runtime 이후에만 존재해야 한다. 그래서 websocket runtime 자체를 authenticated runtime 이후로 이동했다. 변경 후 흐름은 아래처럼 바뀌었다. public render → auth confirmed → realtime runtime import → websocket connect 즉: * localStorage.auth_token 단독 ❌ * stale current_user.data ❌ * id/uuid처럼 보이는 값 단독 ❌ 으로는 realtime runtime이 열리지 않는다. 실제 authenticated context가 확인된 뒤에만: loadWebSocketManager() 가 호출된다. [적용한 분리] 이번 작업에서 적용한 핵심은 아래 네 가지다. 1. WebSocket runtime lazy boundary 유지 초기 core chunk에는 websocket runtime을 포함하지 않는다. template-engine ↘ dynamic import ↘ WebSocketManager 형태로 유지했다. 즉: * laravel-echo * pusher-js * realtime subscribe runtime 은 initial public bundle에 포함되지 않는다. 2. realtime datasource와 websocket runtime 분리 기존에는 datasource scan 자체가 websocket runtime import를 유발할 수 있었다. 이제는: realtime datasource인지 확인 → channel type 확인 → auth context 확인 → 그 다음 websocket runtime import 순서로 변경했다. 즉 import 이전에 capability gate를 둔 셈이다. 3. public realtime과 private realtime 분리 public realtime datasource는 계속 허용한다. 하지만: private presence 채널은 strict auth context가 없으면 runtime import 자체를 하지 않는다. 이 차이는 중요하다. 이전에는: "구독 실패" 수준이었다면, 이제는: "runtime 자체를 생성하지 않음" 으로 바뀌었다. 4. AuthManager만 인증 상태를 소유 이전에는 여러 위치가 인증 상태처럼 동작할 수 있었다. 이번에는: AuthManager → _global.__auth 만 인증 상태를 동기화한다. 즉: * stale storage * partial datasource * user-like cache 같은 값은 authenticated runtime의 기준이 되지 않는다. [결과] 변화 자체는 작아 보일 수 있다. Lighthouse 숫자는 크게 달라지지 않을 수도 있다. 하지만 runtime 관점에서는 꽤 큰 차이다. public runtime이: * realtime capability * websocket runtime * authenticated transport 를 더 이상 소유하지 않게 되었기 때문이다. 이번 수정 이후 anonymous initial load에서는: * websocket chunk import 없음 * websocket 101 없음 * /broadcasting/auth 없음 상태로 정리되었다. [정리] frontend runtime에서 중요한 건: "무엇을 늦게 로드했는가" 보다, "어떤 capability를 어느 runtime boundary 뒤에 두었는가" 에 더 가깝다. 이번 작업은 websocket 최적화라기보다: * public runtime * authenticated runtime * realtime runtime 을 분리하는 작업이었다.

댓글과 작업 영역을 나중에 불러옵니다

필요할 때 댓글과 작업 영역을 불러옵니다. 댓글 0개