3-4. PostMessage와 iframe 모드 25.12.24 ~ 25.12.25

문서 사이트에 데모를 넣고 싶다

세션 리플레이까지 만들고 나니, 이걸 남한테 보여주고 싶어졌다. 문서 사이트에 "여기 눌러보세요, 바로 재생됩니다" 같은 데모를 넣으면 설명이 한결 쉬워진다.

그런데 문제가 있었다. CRD 아키텍처는 클라이언트와 Inspector 사이에 WebSocket 릴레이 서버가 있다. 문서 사이트는 GitHub Pages 같은 정적 호스팅이라 서버가 없다. 데모용으로 WebSocket 서버를 하나 파서 24시간 돌리자니 비용이 부담됐고, "문서만 보여주는 사이트에 서버까지 둘까?" 하는 생각에 망설여졌다.

PostMessage로 서버 없이 통신하기

그래서 PostMessage 트랜스포트를 만들었다(PR #16, devtools-frontend PR #5). WebSocket 대신 iframe의 postMessage로 CDP 메시지를 주고받는 방식이다.

문서 사이트 페이지 안에 데모용 iframe을 하나 띄우고, 그 iframe 안에는 CDP 클라이언트 스크립트가 붙은 미니 페이지가 로드된다. Inspector UI는 문서 사이트(부모) 쪽에 두고, iframe(자식)과 부모 창이 postMessage로 CDP 메시지를 주고받게 했다.

[문서 사이트 (부모)]
  ├── Inspector UI
  └── <iframe>
        └── CDP 클라이언트 + 데모 페이지

같은 오리진이 아니어도 postMessage만 열어두면 되니까, 별도 WebSocket 서버 없이도 "문서 사이트만 열면 데모 재생이 된다"는 걸 맞출 수 있었다.

CDP 도메인 리팩토링

PostMessage 트랜스포트를 만들면서, 기존 CDP 도메인 코드가 WebSocket에 하드코딩되어 있다는 걸 깨달았다. 트랜스포트 레이어를 추상화해서, WebSocket이든 PostMessage든 같은 CDP 도메인 코드가 동작하도록 리팩토링했다(PR #17).

이건 좀 귀찮은 작업이었지만, 나중에 다른 트랜스포트(예: React Native의 네이티브 브릿지)를 추가할 때 편해지는 투자였다.

12월 25일, 크리스마스에도 코딩을 계속했다. Popup Console 관련 문서를 정리하고(PR #20), DevTools Playground를 문서 사이트에 임베드하는 작업을 했다(PR #21).

DevTools Playground는 문서 사이트 방문자가 직접 CDP 메시지를 보내보고 결과를 확인할 수 있는 인터랙티브 데모다. PostMessage 트랜스포트 덕분에 서버 없이도 동작한다.

CSS도 좀 손봤다(PR #18). Inspector UI가 기본 상태로는 좀 투박했는데, Tailwind로 정리하니까 제법 볼만해졌다. 그리고 서버 코드도 리팩토링했다(PR #19). 초반에 급하게 짠 서버 코드를 정리하는 작업인데, 이때쯤 되니까 "처음부터 좀 깔끔하게 짤걸" 하는 후회가 슬슬 올라왔다.

문서 사이트 빌드 이슈

문서 사이트는 rspress(v2)로 만들고 있었는데, devtools-frontend 파일과 rspress 빌드가 충돌하는 문제가 있었다(PR #22). rspress 빌드 과정에서 devtools-frontend의 일부 파일이 빈 파일로 덮어써지는 현상이 발생했다.

devtools_app.js 같은 파일이 0바이트가 되면서 DevTools가 Common2 is not defined 에러를 뿜었다. 빌드 스크립트를 수정해서 devtools-frontend 파일은 rspress 빌드 파이프라인에서 제외하도록 했다. 문서 사이트 빌드 시스템과 DevTools 빌드 시스템이 같은 디렉토리에서 충돌하는 건, 이런 구조에서 흔히 겪는 문제인 것 같다.

12월 25일 요약

크리스마스를 코딩으로 보내면서 PostMessage 트랜스포트, Playground 데모, 문서 개선까지 해치웠다. 이제 문서 사이트만 열면 서버 없이도 CRD 데모를 돌려볼 수 있게 됐다.

이 시점에서 CRD는 "원격 디버깅 도구"를 넘어서 "개발자 경험 플랫폼" 같은 느낌이 되기 시작했다. WebSocket으로도 되고, PostMessage로도 되고, 오프라인에서도 리플레이가 된다. 처음에 배민 따라하기로 시작했는데, 어느새 배민이 안 한 것까지 하고 있더라.

1줄 요약

WebSocket 없이 문서 사이트에서 데모를 돌리기 위해 PostMessage 트랜스포트를 구현했고, DevTools Playground를 만들어서 방문자가 직접 CRD를 체험할 수 있게 했다.