
개인용 도구에서 엔터프라이즈 플랫폼으로: Eidetic OS의 향후 방향
요약
개인용 AI 대화 기록 저장 스크립트에서 시작하여, 하이브리드 RAG와 160개 이상의 스킬을 갖춘 개인용 AI 운영체제인 Eidetic OS로 발전시킨 과정을 다룹니다. Obsidian 마크다운 형식을 활용하여 데이터의 가독성과 Git 버전 관리를 확보한 아키텍처 설계 결정 사항을 공유합니다.
핵심 포인트
- 하이브리드 RAG 및 플러그형 벡터 백엔드 구현
- Obsidian 마크다운 기반의 데이터 저장으로 가독성 및 Git 관리 확보
- 기억 감쇠 점수(memory decay scoring)를 통한 효율적 정보 관리
- 개인용 도구에서 엔터프라이즈 플랫폼으로의 확장 가능성 제시
6개월 전, 저는 Claude와의 대화 내용을 마크다운 (markdown) 파일로 저장하는 Python 스크립트를 만들었습니다. 오늘날 이것은 160개 이상의 스킬 (skills), 하이브리드 RAG 검색, 플러그형 벡터 백엔드 (vector backends), 웹 대시보드, 사실 추출 (fact extraction), 기억 감쇠 점수 (memory decay scoring), 그리고 Obsidian 플러그인을 갖춘 완전한 개인용 AI 운영체제 (operating system)가 되었습니다. 여기에는 각 결정이 어떻게 내려졌는지, 무엇을 시도했고 무엇이 실패했는지, 그리고 다음 단계는 어디인지에 대한 기술적인 이야기가 담겨 있습니다.
내가 이것을 만든 이유
저는 IT 운영 매니저입니다. 저는 아키텍처 설계, 디버깅 (debugging), 코드 리뷰 (code review), 리서치 등 매일 AI를 사용합니다. 문제는 탭을 닫을 때마다 모든 대화 내용이 사라진다는 것이었습니다. Claude에게 제 인프라를 설명하는 데 한 시간을 쓰고 훌륭한 조언을 얻었지만, 다음 세션에서는 다시 처음부터 시작해야 했습니다.
처음에는 뻔한 해결책들을 시도해 보았습니다. 대화 기록 (conversation history)? 너무 노이즈가 많았습니다. 수정 사항, 탈선, 도구 출력값으로 가득 차 있었죠. 노트를 복사해서 붙여넣기? 일주일 이상은 지속되지 않았습니다. 제3자 도구들? 클라우드에 의존하거나 (개인정보 보호 문제) 너무 기본적인 기능만 제공했습니다.
그래서 저만의 것을 만들었습니다. 핵심 논지는 다음과 같습니다: 당신의 AI는 모든 것을 기억해야 하며, 당신이 잠든 동안에도 작동해야 합니다. 그 이후의 모든 과정은 이 목적을 위해 수행되었습니다.
아키텍처 결정 (및 그 이유)
┌──────────────────────────────────────────────────────────┐
│ eidetic CLI │
│ init · doctor · search · embed · dashboard · skills │
...
왜 Obsidian 마크다운인가 (데이터베이스가 아닌 이유)
첫 번째 결정은 저장 형식(storage format)이었습니다. 첫날부터 SQLite를 사용하거나, Postgres, 또는 목적에 맞게 구축된 지식 그래프 데이터베이스 (knowledge graph database)를 사용할 수도 있었습니다. 저는 Obsidian 보관함 (vault) 내의 일반 마크다운 파일을 선택했습니다. 그 이유는 다음과 같습니다:
- 사람이 읽을 수 있음 (Human-readable) — 어떤 파일이든 텍스트 에디터로 열어서 읽을 수 있습니다. 내 기억을 조사하기 위해 특별한 도구가 필요하지 않습니다.
- Git 버전 관리 (Git-versioned) — 모든 변경 사항이 커밋(commit)이 됩니다. 무료로 버전 관리, 브랜칭(branching), 차이점 비교(diffing), 충돌 감지(conflict detection)를 사용할 수 있습니다.
- 이식성 (Portable) — 폴더를 다른 기기로 옮기기만 하면 모든 것이 작동합니다. 데이터베이스 마이그레이션(database migrations)이나 서버 프로세스가 필요 없습니다.
- Obsidian 네이티브 (Obsidian-native) — 저는 이미 개인 메모를 위해 Obsidian 환경에서 생활하고 있었습니다. 보관함(vault)은 나의 지식 베이스(knowledge base)이자 AI의 메모리입니다. 단일 진실 공급원(One source of truth)이 됩니다.
트레이드오프(trade-off): 마크다운(markdown)은 의미 단위로 검색할 수 없습니다. 바로 이 지점에서 RAG 파이프라인(RAG pipeline)이 필요합니다.
하이브리드 검색 (Hybrid Search: BM25 + Vector + RRF + TF-IDF) 이 필요한 이유
순수 벡터 검색(Pure vector search)은 우아하게 들립니다. 모든 것을 임베딩(embedding)하고, 유사한 청크(chunk)를 찾으면 끝이니까요. 하지만 실제로는 정확한 일치(exact matches)를 계속 놓칩니다. 만약 제가 "sqlite-vec"를 검색한다면, 임베딩 검색은 "일반적인 벡터 데이터베이스(vector databases in general)"에 관한 결과는 반환하지만, 제가 해당 라이브러리를 선택했던 구체적인 청크는 놓치게 됩니다.
순수 키워드 검색(Pure keyword search, BM25)은 정확한 용어는 잡아내지만 개념적 연결은 놓칩니다. "인증 방식에 대해 무엇을 결정했었지?"라고 질문하면 "JWT 토큰 검증 전략(JWT token validation strategy)"에 대해 이야기하는 청크를 찾아내지 못합니다.
그래서 우리는 두 방식을 결합합니다:
- BM25: 단어 빈도(term frequency)에 따라 점수를 매깁니다 (정확한 일치를 잡아냄)
- 벡터 코사인(Vector cosine): 의미적 유사성(semantic similarity)에 따라 점수를 매깁니다 (개념적 일치를 잡아냄)
- 상호 순위 결합 (Reciprocal Rank Fusion, RRF): k=60을 사용하여 두 순위 목록을 병합합니다 (어느 한 방식이 지배하는 것을 방지함)
- TF-IDF 재순위화 (TF-IDF reranking): 상위 결과들을 정교화합니다 (희귀하고 쿼리에 특화된 용어의 점수를 높임)
쿼리(Query): "우리는 어떤 벡터 데이터베이스를 선택했었지?"
│
├──► BM25 키워드 검색 ──► "vector", "database"가 포함된 청크들
...
이것은 프로젝트 전체에서 단일 항목 중 가장 큰 품질 향상이었습니다. 순수 벡터 검색에서 하이브리드로 넘어간 것은 즉각적으로 체감되었습니다. 갑자기 시스템이 정확한 라이브러리 이름과 그것을 선택한 이유를 모두 찾아낼 수 있게 되었습니다.
왜 SQLite-vec인가 (Pinecone/Weaviate/Qdrant가 아닌 이유)
약 10,000개의 청크(chunk)를 가진 개인용 지식 베이스(knowledge base)를 위해서는 벡터 데이터베이스(vector database) 서비스가 필요하지 않습니다. 대신 다음과 같은 조건이 필요합니다:
- 설정이 전혀 필요 없음 (zero configuration)
- Python 프로세스 내에 임베드됨 (별도의 서버 실행 불필요)
- 클라우드 의존성이 없음
- 10,000개의 벡터에 대한 KNN(K-최근접 이웃) 검색을 수행하기에 충분히 빠름
sqlite-vec은 이 모든 것을 수행합니다. 이것은 SQLite 확장 기능(extension)입니다. 여러분의 벡터는 메타데이터(metadata)와 동일한 데이터베이스에 저장됩니다. pip install만 하면 끝납니다.
SQLite의 용량을 초과하는 사용자를 위해 우리는 플러그인 방식의 대안으로 LanceDB와 ChromaDB를 추가했습니다 (설정 한 줄로 교체 가능). 하지만 99%의 개인적 용도에는 SQLite가 정답입니다.
왜 로컬 LLM인가 (단순히 클라우드 API만 사용하는 것이 아닌 이유)
모든 임베딩(embedding), 모든 검색, 모든 분석을 여러분의 하드웨어에서 실행할 수 있습니다. 우리는 시작 시 LM Studio, Ollama, llama.cpp를 자동으로 감지합니다. API 키도 필요하지 않습니다.
이것은 이념적인 문제가 아니라 실용적인 문제입니다. 저는 비행기 안에서도 작업합니다. 데이터를 클라우드 API로 전송하는 것이 선택지에 없는 환경에서도 작업합니다. 그리고 여러분의 완전한 전문적 맥락(professional context)을 저장하는 시스템의 경우, 임베딩을 로컬에 유지하는 것은 사치가 아니라 필수 요구 사항입니다.
우리는 클라우드의 속도를 원하는 사람들을 위해 OpenAI 호환 API도 또한 지원합니다. 하지만 시스템은 기본적으로 완전히 오프라인 상태에서도 작동합니다.
왜 확장 기능인가 (단일 구조의 CLI가 아닌 이유)
v2.0에 이르렀을 때, CLI는 1,500줄에 달하는 괴물이 되어 있었습니다. 트레이딩 명령, 음성 합성, 작업 추적 등이 모두 하나의 파일에 들어 있었습니다. 모든 사용자가 모든 기능을 가져야만 했습니다. 모듈을 추가하려면 코어(core)를 수정해야 했습니다.
v3.0에서는 setuptools entry-points를 사용하는 플러그인 방식의 확장 시스템으로 이를 완전히 분해했습니다:
pip install eidetic-os # 코어(Core)만 설치
pip install eidetic-os[trading] # + 트레이딩(trading) 모듈
pip install eidetic-os[voice] # + 음성 합성(voice synthesis)
...
각 확장 프로그램은 자신만의 명령어(commands), 기술(skills), 스케줄(schedules)을 등록하는 EideticExtension 서브클래스입니다. 하나의 확장 프로그램이 로드에 실패하더라도 나머지는 계속 작동합니다. 이는 커뮤니티 기여를 위해 필수적이었습니다. 문서화 도구를 추가하기 위해 반드시 트레이딩(trading) 모듈을 이해해야 할 필요는 없어야 하기 때문입니다.
왜 AST 보안 스캐닝인가 (단순한 샌드박싱이 아닌 이유)
160개 이상의 커뮤니티 기술(skills)이 있는 상황에서, 누군가는 의도적이든 아니든 결국 위험한 동작을 수행하는 코드를 작성하게 될 것입니다. 샌드박싱(Sandboxing)은 런타임(runtime) 문제(무한 루프, 메모리 폭탄, 파일 접근 등)를 잡아냅니다. 하지만 그것은 '의도(intent)'를 잡아내지는 못합니다.
AST 스캐너는 실행 전 코드의 구조를 읽습니다:
- BLOCK —
os.system(),subprocess.call(), 네트워크 접근, 파일 삭제. 즉시 차단되며 절대 실행되지 않습니다. - WARN — 동적 임포트(Dynamic imports), eval/exec, 광범위한 파일 접근. 로그에 기록되며 승인이 필요합니다.
- INFO — 외부 라이브러리 임포트, 볼트(vault) 파일 읽기. 기록되지만 허용됩니다.
이것이 심층 방어(defense in depth)입니다. 스캐너는 샌드박스가 시작되기도 전에 위험한 패턴을 잡아냅니다. 서로 다른 탐지 강점을 가진 두 개의 독립적인 계층이 존재하게 됩니다.
왜 사실 추출인가 (원시 전사 데이터 저장 방식이 아닌 이유)
v1부터 v3까지는 원시 세션 전사(raw session transcripts)를 저장했습니다. 모든 대화를 토씨 하나 틀리지 않고 그대로 저장했습니다. 이는 두 가지 문제를 일으켰습니다:
- 컨텍스트 팽창 (Context bloat) — 대화에는 노이즈가 가득합니다. 말실수, 수정, "아니 잠시만요, 다시 생각해 볼게요"와 같은 내용들입니다. 이 모든 것을 임베딩(Embedding)하면 검색 결과가 오염됩니다.
- 중복성 (Redundancy) — 동일한 결정이 여러 세션에 걸쳐 논의됩니다. 결국 약간씩 다른 단어로 같은 내용을 말하는 다섯 개의 청크(chunks)를 갖게 됩니다.
v4.0에서는 Mem0 스타일의 사실 추출 (fact extraction) 기능이 도입되었습니다. "우리는 인증에 대해 논의했고, JWT 토큰을 사용하기로 결정했습니다. 왜냐하면..."과 같이 저장하는 대신, 시스템은 다음과 같이 추출합니다: "Paul은 인증을 위해 JWT 토큰을 선택함 (결정일: 2026-05-15, 이유: 무상태성(stateless), 세션 DB 불필요)"
각 사실(fact)에는 다음 프로세스가 적용됩니다:
- 기존 사실들과의 코사인 유사도 (Cosine similarity) 비교
- 중복 탐지 (Duplicate detection) — 만약 해당 사실이 이미 존재한다면, 액세스 횟수(access count)를 높입니다.
- 모순 처리 (Contradiction handling) — 새로운 사실이 기존 사실과 모순될 경우, 새로운 사실로 대체합니다 (기존 사실은 비활성 상태로 표시).
- 병합 로직 (Merge logic) — 새로운 사실이 기존 사실을 확장하는 경우, 두 내용을 결합합니다.
이를 통해 컨텍스트 팽창 (context bloat) 현상을 극적으로 줄였습니다. 시스템은 '논의(discussions)'가 아닌 '결정(decisions)'을 저장합니다.
메모리 감쇠 (Memory Decay)를 사용하는 이유 (영구 저장소가 아닌 이유)
모든 사실이 영원히 동일한 관련성을 갖는 것은 아닙니다. "Paul은 다크 모드를 선호한다"는 영구적입니다. 반면 "배포 대상은 staging-3이다"는 일시적입니다. 감쇠 (decay) 기능이 없다면, 오래된 사실들이 쌓여 활성 추론 (active reasoning)을 오염시키게 됩니다.
유지 모델(retention model): P(M) = e^(-λt) · (1 + βf)
- λ = 시간적 감쇠율 (temporal decay rate)
- t = 마지막 액세스 이후 경과 시간
- f = 액세스 빈도 (access frequency)
- β = 강화 계수 (reinforcement coefficient)
자주 액세스되는 사실은 '핫(hot)'한 상태로 유지됩니다. 강화되지 않은 오래된 사실은 비활성화 상태를 향해 감쇠합니다. 슬립타임 데몬 (sleeptime daemon)은 사용자가 오프라인 상태일 때 이 점수 산정 과정을 실행하여, 오래된 컨텍스트를 자동으로 정리(pruning)합니다.
채널 어댑터 (Channel Adapters)를 사용하는 이유 (터미널 전용이 아닌 이유)
사용자가 책상에 앉아 있을 때만 작동하는 개인용 AI OS는 절반의 솔루션에 불과합니다. 채널 어댑터 (channel adapter) 프레임워크를 통해 Slack이나 Telegram에서도 지식 베이스 (knowledge base)를 쿼리할 수 있습니다. 시스템은 로컬 데몬 (local daemon)으로 실행되며, 메시지를 수신하고, 이를 RAG 검색을 통해 라우팅한 뒤, 답변을 다시 보냅니다.
이는 Letta의 커스텀 채널 (custom channels) 아키텍처에서 직접적인 영감을 받았습니다. 핵심 통찰은 지능 (intelligence)과 인터페이스 (interface)를 분리하는 것입니다. 동일한 RAG 파이프라인이 CLI, 대시보드, Obsidian 플러그인, 그리고 메시징 앱에 서비스를 제공합니다.
향후 방향: v5.0
Letta ($10M 펀딩), Mem0 ($24M Series A), 그리고 Nucleus MCP에 대한 경쟁 분석 결과, "개인용 도구"와 "엔터프라이즈 플랫폼" 사이에는 두 가지 격차가 있음이 드러났습니다: 바로 **검증 (verification)**과 **출처 (provenance)**입니다.
신뢰의 문제
AI 에이전트가 자율적으로 코드를 실행할 때, 질문은 "작업을 수행할 수 있는가?"가 아닙니다. 질문은 "그것이 작업을 올바르게 수행했음을 _증명_할 수 있는가?"입니다.
금융, 의료, 정부와 같은 규제 산업에서는 모든 자율적 행동에 대해 변조 방지 기능이 있는 감사 추적 (audit trail)이 필요합니다. 우리의 JSONL 로그는 모든 것을 캡처하지만, 파일 시스템 접근 권한이 있는 사람이라면 사후에 이를 수정할 수 있습니다. 또한 코드 실행의 경우: 우리는 위험 (danger) 여부를 확인하지만 (AST 스캐닝), 정확성 (correctness) 을 검증하지는 않습니다.
구조화된 검증 게이트 (Structured Verification Gates, #29)
자율 실행 전에 실행되는 5단계 파이프라인입니다:
- SYNTAX (구문) — AST 파싱을 통해 실행 전 오류를 포착합니다.
- IMPORTS (임포트) — 종속성 해결 여부를 확인하고 보안 차단 목록 (security block list)과 교차 참조합니다.
- TESTS (테스트) — 해당 모듈에 대한 테스트가 존재하는 경우 이를 실행합니다.
- RUNTIME (런타임) — 샌드박스 (sandbox) 내에서 실행하고 출력 및 리소스 사용량을 캡처합니다.
- DIFF (차이) — 변경된 내용을 보여주고 예상치 못한 수정을 플래그(flag)로 표시합니다.
Code/Skill ──► SYNTAX ──► IMPORTS ──► TESTS ──► RUNTIME ──► DIFF ──► ✅ Execute
│ │ │ │ │
▼ ▼ ▼ ▼ ▼
...
각 단계는 타입이 지정된 결과 (typed result)를 생성합니다. 실행은 첫 번째 BLOCK 수준의 실패 발생 시 중단됩니다. 모든 결과는 감사 추적 (audit trail)에 기록됩니다.
암호화된 감사 서명 (Cryptographic Audit Signatures, #30)
모든 감사 추적 항목에 Ed25519 서명을 적용하며, SHA-256 해시 체인 (hash chain)을 통해 각 항목을 이전 항목과 연결합니다. 생성 후 항목이 수정되면 체인이 끊어지고 검증에 실패하게 됩니다.
Entry 1 Entry 2 Entry 3
┌──────────┐ ┌──────────┐ ┌──────────┐
│ action │ │ action │ │ action │
...
이것은 감사 추적(audit trail)을 단순한 "로그 파일"에서 "실행 이력에 대한 암호학적 증명 (cryptographic proof of execution history)"으로 변화시킵니다. 어떠한 클라우드 서비스 없이도 SOC2, EU DORA 및 MAS TRM을 지원합니다.
계층형 메모리 (Tiered Memory, #31)
단일 벡터 저장소(flat vector store)에서 Core (hot context, 핵심 컨텍스트) / Recall (recent cache, 최근 캐시) / Archival (cold storage, 아카이브 저장소) 구조로 전환합니다. 에이전트는 메모리 감쇠 점수(memory decay scoring)를 사용하여 무엇을 활성 상태로 유지하고 무엇을 아카이브할지 정보에 기반한 결정을 내립니다.
Valkey Search (#32)
검색 지연 시간(retrieval latency)이 중요한 다중 사용자 배포를 위한 고성능 검색 백엔드입니다. 개인용 사용자를 위해서는 SQLite-vec을 설정이 필요 없는(zero-config) 기본값으로 유지합니다.
철학 (The Philosophy)
Eidetic OS의 모든 결정은 세 가지 원칙으로 귀결됩니다:
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기
