본문으로 건너뛰기

resumate 01. Claude Code CLI 로그인 재사용과 캐릭터 3인조 설계

·8 min read·1 / 8

claude CLI에 저장된 로그인을 그대로 재사용하는 데스크톱 앱을 만들기 시작했다. 코딩 에이전트로 출발했다가 취업 코칭으로 방향을 틀었고, 캐릭터 3인조를 설계하고 Tauri와 Bun으로 스택을 잡은 뒤 채팅이 도는 데까지 갔다.

Pro 구독료를 냈는데 API 비용을 또 내야 하나

Claude Code Pro를 쓰다가 이상한 생각이 들었다. 나는 API 비용을 따로 내고 Claude를 쓰는데, Pro 구독료는 이미 내고 있다.

claude CLI는 API 키로 돌아가지 않는다. claude login을 한 번 하면 OAuth로 받은 토큰이 로컬에 저장되고, 그다음부터는 그 토큰으로 구독 계정에 붙는다. 그럼 CLI를 서브프로세스로 띄우기만 하면 내 앱도 그 로그인에 얹혀 갈 수 있다. 키를 발급받아 앱에 넣을 필요가 없다. 이 하나에서 프로젝트가 시작됐다. 사용자가 내는 비용은 이미 내고 있던 구독료 월 20달러가 전부고, 추가로 나가는 API 비용은 없다.

방법은 단순하다. claude -p "프롬프트"를 서브프로세스로 실행하고, stdout으로 나오는 JSON 스트림을 파싱해서 SSE로 프론트엔드에 전달한다. SSE(Server-Sent Events)는 서버에서 클라이언트로 단방향 실시간 데이터를 보내는 HTTP 기반 프로토콜이라 스트리밍 응답에 맞는다. 이 중계는 Bun과 Hono로 만든 사이드카 서버가 맡는다.

코딩 에이전트를 만들다가 방향을 틀었다

처음엔 코딩 에이전트를 만들려 했다. Architect, Builder, Reviewer로 코딩 워크플로우를 분담하는 3인조. 그런데 만들다 보니 범용 코딩 도구는 이미 널려 있었다. 이미 있는 걸 또 만드는 일이다.

그래서 취업 준비생을 위한 AI 코치 3인조로 피벗했다. Architect/Builder/Reviewer는 만들기 쉬웠을 것이다. 취업 코칭은 뭘 만들어야 하는지부터 알아내야 한다.

세 마리 고양이에게 역할을 나눴다

캐릭터 설계가 가장 재밌었다. 기능 분리가 아니라 사용자가 감정적으로 연결될 수 있는 페르소나를 만들고 싶었다.

Nyx는 이력서 분석가다. 냉철하고 날카롭고, 칭찬보다 개선점을 먼저 찾는 고양이다. 이력서를 올리면 구조, 표현, 강점과 약점을 조목조목 짚어준다.

Paws는 기업 맞춤 테일러다. 채용공고 URL 하나를 던지면 기업이 원하는 게 뭔지 뽑아내고, 사용자 이력서를 그 언어로 재구성한다.

Echo는 면접 코치다. 예상 질문을 뽑아주고, 답변하면 면접관처럼 피드백한다. 100번 물어보면 100번 다 다르게 대답할 수 있게 될 때까지.

Electron 대신 Tauri를 고른 건 번들 크기 때문이었다

ElectronTauri
최소 번들 크기약 80MB약 8MB
메모리 사용높음낮음
시스템 APINode.jsRust

macOS 네이티브 앱처럼 동작해야 했고 파일 시스템 접근도 필요했다. Tauri v2와 Rust 레이어가 맞았다.

사이드카를 Node.js 대신 Bun으로 짠 것도 이유가 있다. 단일 바이너리 컴파일이 되니까 Tauri sidecar로 패키징하기 훨씬 편하다. Tauri sidecar는 메인 앱 프로세스가 외부 바이너리를 함께 번들링해서 실행하는 기능인데, Bun 서버를 이 방식으로 넣으면 사용자가 Node.js 런타임을 따로 설치하지 않아도 된다.

하루 만에 채팅이 도는 데까지 갔다

생각보다 많이 됐다. Tauri v2 앱 기반 구조를 세우고 사이드카가 앱과 함께 자동으로 뜨게 했다. 사이드카에는 채팅, 스킬, 파일 목록 엔드포인트를 가진 HTTP 서버를 올리고, claude CLI 서브프로세스의 출력을 SSE로 흘려보냈다.

프론트엔드는 React 채팅 UI를 붙였다. 스트리밍 렌더링, 도구 호출 표시, 중단 버튼까지 들어갔다. 화면 위에 떠 있는 CharacterDock 플로팅 위젯은 드래그로 옮길 수 있고, Nyx·Paws·Echo 세 캐릭터가 Lottie 애니메이션으로 움직인다. 대화 세션은 Zustand로 캐릭터마다 독립시켰고 SQLite에 저장했다. NyxView, PawsView, EchoView 레이아웃도 각각 잡아뒀다.

아직 안 된 건 CharacterBlob 3D 컴포넌트, 캐릭터별 시스템 프롬프트의 취업 특화, 이력서 PDF 파싱, 채용공고 URL 스크래핑이다.

UI보다 UX 결정이 더 어려웠다. 작업창을 어떻게 열고 닫을 것인가, 드래그와 클릭을 어떻게 구분할 것인가 같은 작은 결정들이 실제로는 엄청나게 많은 코드와 연결돼 있었다. 그리고 캐릭터에 감정을 넣는 게 생각보다 중요했다. 기능만 있는 도구는 쓰기 싫어진다. 고양이 캐릭터가 Lottie로 살아 움직이는 걸 보면 더 쓰고 싶어진다. 그 차이가 결국 사용 지속성을 만든다.