프로젝트

선택 프로젝트 — 개인 프로젝트

Refract-AI

여러 AI 서비스를 같이 쓰는 사람은 브라우저 탭을 오가며 같은 질문을 반복 입력하고, 탭이 늘수록 브라우저는 점점 무거워집니다. 각 서비스의 로그인 세션과 보안 정책은 그대로 유지한 채, 한 화면에서 동시에 묻고 나란히 비교할 수 있는 가벼운 데스크톱 앱을 만들었습니다.

1인 개발 · 아키텍처 설계·구현/개인 프로젝트/Tauri 2 / Rust / Vanilla JavaScript (ES Modules) / Vite 6 / Tauri Capabilities (ACL)
Refract-AI

01 / 03

네이티브 웹뷰 4개를 한 창에

iframe과 Electron BrowserView 대신, 하나의 Tauri 윈도우 위에 서비스별 네이티브 자식 웹뷰를 런타임에 동적으로 마운트합니다. 그리드/컬럼 레이아웃과 서비스 on/off에 따라 배치가 즉시 다시 계산됩니다.

데모 확인 ↗

해결한 문제

  • 4개 AI 서비스를 한 화면에 띄우려 iframe을 먼저 검토했지만 X-Frame-Options와 CSP로 렌더링 자체가 막혔습니다. 대안으로 검토한 Electron의 다중 BrowserView는 4개 세션을 동시에 켜면 유휴 상태에서도 RAM을 1.2GB 넘게 먹어 프레임이 드랍됐습니다.

내가 기여한 것

  • Chromium을 통째로 번들링하는 Electron 대신 OS 내장 렌더러를 직접 제어하는 Tauri 2(Rust)를 골라, 하나의 윈도우 위에 서비스별 네이티브 자식 웹뷰를 런타임에 동적으로 마운트·언마운트하는 구조로 설계했습니다. 레이아웃 좌표는 프론트엔드에서 100ms 디바운스로 계산한 뒤 Rust의 update_all_bounds 커맨드 하나로 일괄 전달해 IPC 트래픽을 줄였습니다.
  • 타깃 서비스의 입력창이 textarea부터 ProseMirror·contenteditable까지 제각각이라 값을 그냥 대입하면 내부 상태와 어긋나 전송이 씹혔습니다. 외부 웹뷰에 라이브러리를 주입하는 대신, InputEvent·KeyboardEvent 시퀀스를 단계별로 트리거하는 의존성 없는 합성 이벤트 파이프라인을 직접 만들고 Tauri Capabilities로 스크립트 실행 권한을 최소한으로 제한했습니다.
  • 격리된 웹뷰끼리는 postMessage로 직접 연결할 수 없어, 웹뷰 안에서 커스텀 URI 스킴(scroll-sync://)을 호출하면 Rust의 on_navigation 훅이 이를 가로채 데이터로 변환하는 경량 IPC를 고안했습니다. 이벤트가 되돌아와 무한 루프에 빠지지 않도록 에포크 토큰 기반 동기화 락과 16ms 스로틀링을 넣었습니다.

임팩트

-68%

메모리 1.2GB → 380MB (Electron 대비)

-85%

배포 크기 120MB → 18MB

99.8%

입력 전송 성공률 · 지연 16ms 이내