이 글은 제 개인적인 경험과 장황한 생각이 담겨 있습니다. 서론을 읽지 않으셔도 됩니다.
서론
요즘 회사를 다니지 않고 혼자 코딩을 하는데, 계획한 일을 준비하기에 효율적인 생활이라고 생각해서 퍼블릭 LLM API 기반의 작은 프로젝트들을 만들어 보고 있다. 기본적인 접근 방식은 이전 글에서 채용 공고 데이터를 활용한 웹을 만들었던 것처럼, “내가 어떤 데이터를 이용할 수 있는가”에 초점을 맞추고 있다. 사용자나 플랫폼의 데이터를 활용하기보다 대화 자체에 감성을 넣는 종류의 캐릭터 챗봇 제품도 있지만, 한 차례 트렌드가 지나갔고 사용자의 선택을 받을 만한 뾰족한 프로덕트를 만들어 내기 힘들 거라 생각했다. 그래서 고민한 것은 서버 없이 웹 브라우저 익스텐션을 만드는 것. 이렇게 해서 사용자의 웹 브라우저 데이터를 이용해 브라우징 UX를 개선하는 프로젝트를 고안했다. 거창하게는 Cursor의 웹 브라우저 버전을 상상했다.
여담이지만 ‘웹 브라우저 개선’이라는 테마는 내가 개발자를 막 시작할 때 가지고 있던 비전이기도 하다. 학교에서 나는 AI 과목을 집중 이수하며 NLP 연구실에서 연구를 하던 중, 웹 브라우저의 UX 측면에서 발전 가능성에 대한 혼자만의 아이디어를 가지고 프론트엔드 개발자로 첫 커리어를 시작했다. 막상 조직 생활을 하다 보니 하입와 권력을 좇다가 잊었던 꿈이 되었지만 말이다.
다소 장황하지만 사실 북극성이 그렇다는 것이고, 내가 그렇게 대단한 제품을 만들어 낸 것은 아니다. 잊었던 기억을 떠올리게 된 것이 반가워 기록하고 싶었다.
물론 LLM 기반으로 브라우징 UX를 개선하는 익스텐션은 이미 시장에 여럿 나와 있다. 대충 훑어본 결과, 이름만 다를 뿐 비슷한 기능 구성을 갖추고 있었다. 주된 유입 요인은 ChatGPT보다 낮은 가격, 탭 전환 없이 사용하는 사이드패널 UI, 콘텐츠 요약 기능 정도다. 부가기능들이 많긴 한데, 대부분 사용자의 시간을 절약해 주는 기능은 아니었다. 주요 익스텐션은 사용자 본인의 API 키를 이용해서 구독 없이도 기본적인 기능을 제공하는데, 페이지 요약과 대조 번역 같은 기능은 유료 플랜으로 묶어 두었다. 구조를 상상했을 때 개발 환경을 잘 잡아두면 금방 구현 가능한 것들이라고 생각했다. 그렇게 직접 개발을 하다 보면 사용자 활동 시퀀스 데이터를 활용해 뾰족한 기능도 만들 수 있을 것이라 생각하지만(결론부터 말하자면) 아직 거기까지 나아가지는 못했다.
이름은 시즈에
. 닌텐도 동물의숲에서 주인공을 돕는 비서 캐릭터 여울이의 본명을 사용했다.
시즈에의 기능
https://github.com/rokrokss/shizue
기능 설명은 이미지로 대신하고, 개발 과정에 대한 기록을 남긴다.
기본적으로 WXT라는 익스텐션 개발 프레임워크를 사용했다. 만들어진 프로덕트에서 실행되는 코드는
-
모든 페이지에 삽입되는 오버레이 메뉴
-
클릭이나 단축키로 열리는 사이드패널
-
브라우저 실행 시 생성되는 백그라운드 프로세스
이렇게 크게 세 가지 컨텍스트로 관리된다. 사용자가 입력하는 API 키는 페이지에 삽입되는 오버레이 메뉴에서 읽으면 안 된다. 다른 앱들과 같은 DOM에서 상태가 조회되면 메시지가 탈취될 가능성이 있다. 또, 오버레이 메뉴와 사이드패널은 해당 웹 조작에 따라 언제든 중단될 수 있도록 비동기 LLM API 호출과 공통 상태 관리는 백그라운드에 위치한다. 그렇다 보니 흡사 클라이언트 <-> 서버
구조처럼 코드베이스를 구성했다.
사이드패널의 채팅
웹 익스텐션은 익스텐션 전용의 key-value 로컬스토리지를 사용할 수 있고, 추가로 indexDB라는 인덱싱과 ACID 트랜잭션이 지원되는 데이터 스토리지가 있다. 설정용 상태 관리에는 로컬스토리지를 사용하고, 채팅 스레드와 메시지에는 indexDB를 사용했다.
에이전트의 대답은 LLM API -> 백그라운드 프로세스 -> 사이드패널
까지 스트리밍 형식으로 출력하도록 구성했다.
원 클릭 페이지 요약
대화 스레드와 메시지가 저장되는 indexDB는 오버레이 메뉴에서 접근할 수 없다. 사이드패널이 열릴 때 행할 액션 타입과 페이지 데이터를 로컬스토리지에 저장하여, 열릴 때마다 초기화되는 사이드패널이 페이지 요약을 트리거할 수 있도록 했다. 이미 채팅 중인 상황이라면 현재 스레드에서 요약이 실행되도록 이벤트 트리거를 구성했다.
대조번역
커스텀 웹 컴포넌트와 스크롤 리스너, 현재 스크린 내의 번역 대상 컴포넌트를 감지하는 DOM 순회 알고리즘을 통한 초안을 전 직장 동료인 @gompu123님께서 구현해주셨다. 근황 얘기할 겸 만들고 있던 걸 공유드렸더니, 본인도 월 1.5만 원 내고 크롬 익스텐션을 쓰고 있었다고, 직접 만들어 보겠다고 해주셨다.
이후 나는 배치 처리와 컴포넌트 큐, 번역 캐시를 적용해 성능과 안정성을 높였다.
다크모드
builder.io 블로그에서 오버레이 메뉴를 색상 반전시키는 걸 보고 같은 방식을 적극 활용했다. 추후에는 컬러 팔레트로 주요 색상 리스트를 모듈화해서 커스텀 테마를 제공하고 싶다.
참고로 시즈에에 사용된 각종 캐릭터 에셋은 5달러를 주고 구매했다.
유튜브 자막 번역
wip…
기술스택
모든 코드는 https://github.com/rokrokss/shizue 에서 볼 수 있다.
- 프레임워크: WXT, React, vite
- 상태관리: Jotai, Dexie
- LLM 호출: LangChain
추후 계획
-
실사용자를 모으기 위해 크롬 익스텐션 웹스토어에 배포 요청을 넣어놓았다. 이 글에는 담기지 않았지만, 원활하게 사용 가능하도록 신경 쓴 부분이 많은데, 얼른 배포돼서 홍보를 하고 싶다. 배포 요청을 하고 보니 설명용 이미지들을 너무 대충 만들어서 한 번 반려될 것 같은데, 그러면 제대로 된 이미지를 만들고 다시 배포 검토가 완료되는 데 시간이 좀 걸릴 것 같다.
-
앞서 언급한 것처럼 사용자를 유입시킬 뾰족한 서비스를 만들고 싶다. 브라우저 히스토리와 사용자 행동 로그를 사용하여 사용자의 시간을 절약해 줄 수 있는 무언가를 만들고 싶은데, 아직 아이디어가 없다. 상용 익스텐션들에도 아직 그런 기능이 보이진 않는다. 고민해볼 시간이 좀 필요한데, 워낙 현생에 닥친 문제들이 많아 금방 가능할 것 같진 않다.
-
만들고 친구한테 설명해 주다 보니 OpenAI API 키를 만들어서 일정 금액을 충전하고 제품에 입력해서 사용하는 것이 거대한 장벽이라는 걸 체감했다. 킬러 기능을 만들고 나면, 프리 티어와 자체 구독 기능을 만들어야 할 필요가 있다.