서론
Electron으로 Chrome 스타일의 브라우저에 AI 사이드바를 추가한 앱을 만들었습니다.
단순히 웹 페이지를 표시하는 것만이 목적은 아니었습니다.
현재 열려 있는 페이지의 URL, 제목, 본문, 선택된 텍스트를 AI에게 전달
AI가 검색, URL 열기, 클릭 등의 조작을 제안
필요하다면 브라우저 조작까지 연결
이 기사에서는 Electron으로 이러한 AI 브라우저를 만들 때, Main, Preload, Renderer를 어떻게 나누었는지 정리합니다.
전체 구성
구성은 매우 정직합니다.
main.js
Electron의 Main Process
BrowserWindow, session, IPC, AI 호출 담당
...
Electron에서는 Renderer에서 Node.js 기능을 직접 다루게 하지 않는 것이 더 안전합니다.
따라서 contextIsolation: true를 전제로 하여, Renderer에서 사용하고 싶은 기능만 preload.js에서 공개했습니다.
preload에서 경계를 만들기
preload에서는 Renderer에 browserAPI를 공개하고 있습니다.
예를 들면 다음과 같은 기능입니다.
askAI
startAIStream
cancelAIStream
...
Renderer는 직접 ipcRenderer를 다루지 않습니다.
Renderer
↓ window.browserAPI.askAI(...)
Preload
...
이 형식을 취하면 UI 측에서는 필요한 조작만 호출할 수 있습니다. 반대로 말하면, 허가되지 않은 조작은 Renderer에서 실행할 수 없습니다.
AI 브라우저와 같이 외부 페이지를 표시하는 앱에서는 이 경계가 매우 중요합니다.
페이지 컨텍스트를 AI에게 전달하기
AI가 페이지 내용을 읽을 수 있도록 현재 탭에서 다음 정보를 수집합니다.
URL
title
selectedText
...
이를 프롬프트(Prompt)에 넣어 Ollama로 전달합니다.
프롬프트에서는 AI가 일본어로 답변할 것과, 필요하다면 액션 태그(Action Tag)를 출력할 것을 지시했습니다.
[ACTION:search:검색 키워드]
[ACTION:open:URL]
[ACTION:click:버튼 텍스트]
...
AI의 응답을 단순히 문장으로 표시하는 것에 그치지 않고, 액션 태그를 Renderer 측에서 해석하여 브라우저 조작으로 연결합니다.
조작 전 확인 단계 넣기
AI가 브라우저를 조작할 수 있게 되면 편리하지만, 위험도 따릅니다.
특히 클릭이나 커맨드 실행은 AI가 실수할 경우 의도하지 않은 조작으로 이어질 수 있습니다.
그래서 대화 모드에서는 조작 전 확인을 넣을 수 있도록 했습니다.
AI가 조작 태그를 출력
↓
Renderer가 감지
...
AI 조작을 도입할 때는 '할 수 있는 것'보다 '멋대로 하지 않는 것'이 더 중요합니다.
스트리밍과 정지
일반적인 AI 답변은 한꺼번에 받는 것만으로도 동작합니다.
하지만 대화 모드에서는 답변이 길어지는 경우가 있습니다. 그래서 Ollama의 streaming을 사용했습니다.
Main 측에서 stream을 읽어 chunk 단위로 Renderer에 보냅니다.
Ollama stream
↓
Main process
...
나아가 정지 버튼도 마련했습니다.
stream 중에는 전송 버튼을 정지 버튼으로 전환하고, AbortController로 처리를 중단합니다.
AI의 응답은 길어질 수 있으므로, 정지할 수 있는 UI는 매우 중요합니다.
로그인 캐시 처리
브라우저로 사용하려면 로그인 상태 유지도 필요합니다.
Electron의 session partition에는 persist:main을 사용했습니다.
또한 Cookie 변경 시 로그인 캐시를 저장하고, 기동 시 복원하는 처리도 포함되어 있습니다.
다만, 이 부분은 주의가 필요합니다.
session cookie까지 무분별하게 복원하면 Google 등에서 Cookie mismatch가 발생할 수 있습니다.
따라서 복원 대상은 신중하게 다룹니다.
session cookie는 복원하지 않음
expirationDate가 없는 것은 피함
이미 session에 있는 cookie는 중복 추가하지 않음
로그인 유지는 편리하지만, 과하면 오히려 망가집니다.
탭, 북마크, 프로필
브라우저로서 최소한의 기능을 갖출 수 있도록 탭 관리, 북마크, 프로필(Profile)도 포함했습니다.
Renderer 측에서는 상태를 통합하여 관리하고 있습니다.
tabs
activeTabId
bookmarks
...
프로필별로 북마크, 확장 프로그램, 비밀번호 정보를 분리합니다.
본격적인 Chrome 호환성을 목표로 하기보다는, "AI와 함께 조사나 작업을 수행하기 위한 가벼운 작업용 브라우저"로서 필요한 기능을 추가해 나가는 방식입니다.
직접 만들어보며 알게 된 점
AI 사이드바가 있는 브라우저에서 어려운 점은 AI의 답변 그 자체보다 경계 설계(Boundary Design)입니다.
고민해야 할 사항이 많습니다.
- Renderer에 Node.js 권한을 부여하지 않음
- preload를 통해 공개 API를 제한함
- AI의 조작은 태그로 명시함
- 위험한 조작에는 확인 단계를 거침
- 스트리밍 (streaming)은 중지할 수 있도록 함
- 쿠키 (Cookie) 복원은 신중하게 처리함
AI를 브라우저에 넣으면 할 수 있는 일은 단번에 늘어납니다.
다만, 그만큼 "어디까지 자동으로 수행하게 할 것인가"를 설계하지 않으면 사용하기 불편해집니다.
요약
Electron으로 AI 사이드바가 있는 브라우저를 만들 때는 Main, Preload, Renderer의 역할 분담이 중요합니다.
이번 설계에서는 Renderer는 UI에 집중하고, OS 조작이나 AI 호출은 Main으로 모았으며, Preload를 통해 안전한 API만 공개했습니다.
AI 기능은 페이지 컨텍스트(Page Context)를 전달하고, 액션 태그(Action Tag)를 반환하며, 확인 후 실행하는 흐름으로 구성했습니다.
AI 브라우저를 만든다면, 우선 "AI에게 무엇을 시킬 것인가"보다 "AI가 멋대로 무엇을 하지 못하게 할 것인가"부터 생각하는 것이 좋다고 생각합니다.
Discussion