katsubee·katsubox 소개, 직접 구축한 AI 채팅
- katsubee는 회사에서 쓸 수 없는 AI 채팅을 로컬 Ollama로 직접 서버에 구축한 것이고, katsubox는 대용량 파일을 떨어뜨리고 정리하는 개인용 파일 드롭이다.
- katsubee는 문서 검색, 운영 질의, 주간 보고 작성에 쓰이고, katsubox는 Docker 이미지 tar를 Windows FTP로 넘기는 경유지다.
- 이 글은 두 서비스 소개이고, 이후 글은 여기서 드러난 개선점을 하나씩 다룬다.
katsubee와 katsubox, 한 줄 소개
katsubee와 katsubox는 내가 직접 구축해 같은 Mac mini 위에서 돌리는 두 서비스다. 같은 Cloudflare 터널을 쓰지만 레포와 프로세스는 분리돼 있다.
katsubee는 로그인 없이 바로 묻고, 로그인하면 대화와 문서가 계정에 남는 LLM 채팅이다. 회사에서는 이런 AI를 쓸 수 없어서 직접 서버에 올려 만들었다. 모델은 로컬 Ollama만 쓰고 대화와 문서의 정본은 자체 Postgres에 둔다. katsubox는 Docker 이미지 tar 같은 큰 파일을 브라우저로 올리고 폴더로 정리하는 파일 드롭 서비스다.


katsubee: 로컬 모델 위에 얹은 채팅
스택은 JDK 25, Spring Boot 4.1, Spring AI, PostgreSQL(pgvector)이다. 내장 UI가 있고 다른 서비스는 UI 없이 /api/v1 API와 SDK(katsubee-client)로 붙는다. 운영 화면은 /admin에 따로 있고 Node 기반 BFF와 React SPA로 만들었다.
채팅은 SSE 스트리밍, 모델 선택과 자동 라우팅, 파일 첨부, 재생성, 긴 대화 롤링 요약, 답변 피드백을 갖췄다. 게스트는 IP 한도 안에서 쓰고, 로그인 방식은 아이디·비밀번호와 패스키(WebAuthn)다. 로그인 세션은 마지막 요청 후 30일 유지된다.
그 밖에 이미지 생성과 사진 바꾸기, 음악 생성, 모델이 만든 문서를 docx·pdf·xlsx·pptx로 바꾸는 산출물 기능이 같은 화면에 있다. 이미지 편집은 Ollama가 입력 사진을 반영하지 않는 것을 실측으로 확인한 뒤 호스트의 별도 편집 서버를 붙였고, 사진은 이 서버 밖으로 나가지 않는다.
이중화 배포와 운영 모니터링
운영 쪽은 이중화 배포, 불변 릴리스와 자동 롤백, 일일 DB 백업, Prometheus와 Grafana, 합성 호출 모니터링으로 구성했다. 어드민에서는 활성 사용자(DAU·WAU·MAU), 가입 주 코호트 리텐션, 모델별 사용량, 감사 로그를 본다. 질의 로그는 작성자 동의와 원문 열람 권한을 분리해서 운영자가 마음대로 대화를 볼 수 없게 했다.
실무에서 쓰는 방식: 문서를 올리고 묻는다
가장 많이 손이 가는 기능은 지식(RAG)이다. 텍스트, PDF, Word, PPTX를 올리면 pgvector로 임베딩하고, 질문하면 벡터 검색과 키워드 검색을 RRF로 합쳐 근거를 찾는다. 답변 아래에는 출처 칩이 붙고, 칩을 누르면 문서 본문이 열리며 인용 구간이 강조된다.
지식은 계정, 대화, 1회 단위로 켜고 끌 수 있다. 프로젝트로 대화를 묶으면 그 프로젝트에 올린 문서만 참고한다. 문서를 외부 서비스에 보내지 않고 답을 받는다는 점이 로컬 모델을 고집하는 이유다.
운영 질문에도 쓴다. 런북과 배포 토폴로지 문서를 빌드 때 함께 번들하고, searchRunbooks, readRunbook, appRuntimeInfo 같은 읽기 전용 도구로 질문에 답하게 했다. 인프라에 그라운딩된 도우미를 채팅 위에 얹은 형태다.
katsubox: 서버에 떨어뜨리고 FTP로 넘긴다
katsubox의 쓰임은 구체적이다. 브라우저로 katsubox에 파일을 올리면 Mac mini의 incoming 폴더에 저장된다. 그 폴더를 Parallels Windows에 공유 폴더로 열고, Windows의 FTP 클라이언트로 원격 서버에 올린다.
대용량 tar는 80MB 청크로
Docker 이미지 tar는 크다. Cloudflare 프록시는 본문이 약 100MB를 넘으면 막기 때문에 큰 파일은 80MB 청크로 나눠 올리고 서버에서 스트리밍으로 조립한다. 다운로드도 진행률이 보이는 스트리밍이다.

화면은 파일 목록이다. 폴더 옆에 글을 쓰는 페이지 항목이 함께 보이고, 위쪽 한 줄 툴바에 새 폴더, 새 텍스트, 새 페이지, 휴지통이 놓여 있다. 삭제는 곧바로 지워지지 않고 휴지통으로 가서 복원할 수 있다.
파일에는 로컬 Ollama가 프로젝트와 주제 분류를 붙인다. 파일명, 경로, 텍스트 앞 500자만 읽고 외부로는 나가지 않는다. 최근에는 파일과 폴더, 페이지에 공유 링크를 만들 수 있게 됐고, 방문자 댓글은 주인이 승인한 뒤에 공개되도록 했다.
Basic 인증과 파일시스템 저장
인증은 HTTP Basic 하나다. 사용자가 한 명이고 신뢰 경계가 Cloudflare 앞단이라 세션이나 OAuth는 과하다고 판단했다. 백엔드는 FastAPI, 저장소는 로컬 파일시스템이다. 최종 목적지가 공유 폴더라 폴더 구조가 곧 메타데이터가 되고, 대용량 tar를 DB에 넣는 부담도 피한다. PWA 매니페스트가 있어서 Chrome이나 Edge에서 앱으로 설치해 쓸 수 있다.
둘을 굴리는 방식: 티켓과 주간 보고
두 서비스 모두 코딩 에이전트가 티켓 단위로 일하는 하네스 위에서 개발한다. 티켓마다 브랜치를 따고, 검증 스크립트와 CI 게이트를 통과해야 머지된다. katsubee는 여기에 채팅 품질 평가(eval) 게이트가 더해져 있다.
매주 월요일에 주간 보고가 만들어진다. 그 주에 머지된 커밋과 티켓, 운영 배포 여부, 디스크와 백업 상태, 쓰는 기술의 새 릴리스가 정리된다. 보고서는 확인하지 못한 것을 확인하지 못했다고 적는 것을 원칙으로 한다. 이 블로그의 주간보고 글이 그 보고서에서 나온다.
드러난 개선점과 다음 글
쓰면서 개선점도 분명해졌다. katsubee는 지식 검색의 키워드 쪽이 자연어 질문 40개에서 0건이었던 것을 찾아 고쳤다. 정답 청크 회수가 0/40에서 33/40이 됐고, 이 과정은 따로 정리했다.
답변 품질과 백업 과제
답변 품질은 방문객 SSID를 비밀번호처럼 답하는 문제가 약 절반 확률로 남아 있어 모델이나 RAG 프롬프트를 바꿀 때 다시 재야 한다.
katsubox는 앨범과 공유 링크 메타데이터가 katsubox.db 하나에만 있어 백업이 핵심이다. 백업 스크립트와 매일 04:10 launchd 설정은 저장소에 들어왔지만, 실제로 자동 실행되는지는 아직 확인하지 못했다. 프런트엔드는 바닐라 JS에서 TypeScript와 React로 옮겨 왔고 번들은 Preact 호환 레이어로 약 430KB에서 약 220KB로 줄였다.
다음 글부터는 이 개선점을 하나씩 다룬다. RAG 검색 개선, 답변 품질 측정, katsubox 백업 자동화 순서로 쓸 예정이다.