
오늘의 RAG 최적해(Hermes Agent/Obsidian)의 뒷이야기
요약
단순한 벡터 검색을 넘어 전문 검색, 문맥 그래프, 질문 메모리 등 4가지 도달 경로를 결합한 RAG 설계 방식을 제안합니다. Hermes Agent와 Obsidian을 활용한 실용적인 지식 기반 구축을 위한 설계 원칙을 다룹니다.
핵심 포인트
- RAG는 단일 벡터 DB가 아닌 다각적 검색 축의 결합체여야 함
- 전문 검색, 벡터 검색, 문맥 그래프, 질문 메모리의 4축 구조 제안
- 모델 번호나 고유명사 등 이산적 기호 검색의 중요성 강조
- Hermes Agent의 MCP 및 지속 메모리 활용 설계
RAG를 「벡터 검색 (Vector Search)」이라고만 생각하면, 상당히 중요한 것을 놓치게 된다.
자신의 Obsidian Vault와 Google Drive를 Hermes Agent에서 검색할 수 있도록 만들려고 시도하면서 보인 것은, 검색에는 적어도 다음 4가지 도달 경로가 있다는 사실이었다.
| 축 | 무엇으로 찾는가 | 불가약성(Irreducibility)의 근원 | 전형적으로 잡을 수 있는 것 |
|---|---|---|---|
| ① 전문 검색 (Full-text Search) | 문자열의 일치 | 이산적인 기호 | 모델 번호, 고유명사, 에러 코드, 함수명 |
| ... | |||
| 이 4가지는 유행하는 검색 알고리즘의 이름이 아니다. 정보가 어디에서 도달하는가의 차이다. |
그래서 나는 오늘날 RAG의 골격은 「단일 벡터 DB (Vector DB)」가 아니라, 전문 검색(Full-text Search)・벡터 검색(Vector Search)・문맥 그래프(Context Graph)・질문의 메모리(Query Memory)를 갖추고, 그 위에서 에이전트(Agent)가 축을 선택하는 구성에 가깝다고 생각한다.
이 기사는 화려한 신기술 소개가 아니다. 오히려 반대로, 너무나 당연해 보이는 4가지 단어를 왜 지금 굳이 나누어 말할 필요가 있는지를 적어두기 위한 것이다.
이 기사는 2026-06-10 시점에서의 나의 설계 메모이며, 동시에 조금 앞을 내다본 전망이기도 하다.
지금 많은 상황에서 RAG는 「벡터 검색을 추가하는 것」과 거의 동의어로 이야기되고 있다. 물론 벡터 검색은 강력하다. 단어의 변형을 넘어 문서를 찾아낼 수 있게 된 것은 정보 검색에 있어 큰 진전이었다.
다만, 실제 서비스의 지식 기반(Knowledge Base)에서 망가지는 것은 그뿐만이 아니다.
모델 번호를 모호하게 검색해서는 안 된다. 의미는 가깝지 않지만 구조적으로 관계된 자료를 놓쳐서는 안 된다. 조직이나 지역, 시계열이 만드는 문맥을 단순한 의미적 근접성으로 뭉개버려서는 안 된다. 그리고 그 사람이 무엇을 어떻게 물어왔는가 하는 궤적을 단순한 「편리한 메모리 기능」으로 소비해서는 안 된다.
내가 여기서 박고 싶은 말은 다음 한 문장으로 요약된다.
검색 설계는 알고리즘의 선택이 아니라, 정보의 도달 경로를 나누는 것에서부터 시작해야 한다.
이 말(말뚝)이 1년 뒤에 어떻게 보일지는 모른다. 4라는 분류 방식이 재편될 가능성도 있다. 하지만 이산적인 기호, 의미 공간, 외생적인 관계, 개인의 질문 궤적이라는 4가지 기원은 그렇게 쉽게 사라지지 않을 것이라고 생각한다.
본고의 출발점은 자신의 Obsidian Vault와 Google Drive를 AI 에이전트(Agent)로부터 실용적으로 검색할 수 있게 하고 싶다는, 상당히 소박한 요구였다.
여기서 다루는 「4축 검색」은 Hermes Agent의 공식 기능을 그대로 설명하는 것이 아니다. Hermes Agent / Obsidian / Google Drive를 사용하여 자신만의 RAG 기반을 구축한다면, 검색층을 어떻게 분리해야 하는가에 대한 설계상의 정리이다.
Hermes Agent에 대해서는 공식 문서에서 다음과 같이 설명되어 있다.
- Nous Research에 의한 self-improving AI agent
- MCP 등을 통해 외부 도구 및 로컬 환경에 접속 가능
- 지속 메모리(Persistent Memory)는
MEMORY.md(프로젝트・규약・배움)와USER.md(그 사람의 프로필)로서~/.hermes/memories/에 저장되어, 세션 시작 시 시스템 프롬프트(System Prompt)로 주입됨 - 과거 세션의 검색은 별도 계통으로,
~/.hermes/state.db의 SQLite에 FTS5 전문 검색(Full-text Search) 기능과 함께 저장됨 - Obsidian Vault를 읽고・검색하고・생성하고・편집하는 bundled skill이 있음 (기억 DB 그 자체는 아님)
따라서 본고에서 말하는 「메모리 축」은 Hermes의 공식 메모리 기능 그 자체와 완전히 동일하지 않다. 공식 메모리, 과거 세션 검색, 스스로 추가하는 질문 로그・검색 로그를 연결하여 생각한 RAG 설계상의 추상화이다. 이 부분을 섞으면 글의 논지가 약해지므로 미리 나누어 둔다.
로컬에 둔 Obsidian Vault와 클라우드의 Google Drive. 이 두 가지를 AI 에이전트로부터 「정말로 검색할 수 있는」 상태로 만들고 싶다. 그렇게 생각하며 손을 움직이는 동안, 나는 정보 검색의 패턴을 차례대로 마주하게 되었다.
처음은 전문 검색(Full-text Search)이었다. Google Drive가 원래 가지고 있는 검색은 이 축에 가깝다. 하지만 「예산」으로 검색했을 때, 본문에 「비용」이라고만 적힌 문서는 찾아낼 수 없다. 벽에 부딪혀 벡터 검색(Vector Search)을 추가했다. 의미로 검색할 수 있게 되었다.
그다음, 의미로는 가깝지 않지만 관련 있는 문서를 놓치고 있다는 사실을 깨달았다. 그래서 Obsidian의 링크 구조나 태그를 살펴보기 시작했다.
더 나아가 생각하면, 문맥(Context)은 Obsidian의 링크에만 국한되지 않는다. EC(전자상거래)로 말하자면 "이 상품을 구매한 사람은 이것도 구매했습니다", 지역으로 말하자면 "당신의 지역에서는 이것이 많이 팔립니다", 시간으로 말하자면 "지금 이 화제를 쫓고 있는 사람은 다음에 이것을 봅니다". 이러한 관계는 문서 본문의 의미만으로는 도출되지 않는다.
그리고 마지막으로, 내가 정말로 찾고 있었던 것은 과거에 내가 어떻게 질문해 왔는가라는 이력 속에도 있다는 사실을 깨달았다.
결과적으로 4가지 검색 패턴이 손에 쥐어졌다. 전문 검색(Full-text Search) · 벡터 검색(Vector Search) · 문맥(Context) · 메모리(Memory).
짧게 쓰면 너무나 당연해 보인다. 하지만 이 4가지 단어는 구현의 부품명이 아니라, 정보의 기원을 나누기 위한 압축된 표현이다. 차례로 마주친 이 4가지를 나는 처음부터 설계한 것이 아니다 —— 하나의 축의 한계가 다음 축을 불러왔다. 그리고 도달한 끝에 있었던 것은 "4가지 편리한 검색 기법"이 아니라, 그 어느 하나로는 원리적으로 덮을 수 없는, 4가지 서로 다른 정보의 기원이었다. 이하, 그 4가지가 "각기 다른 이유로" 대체될 수 없음을 보여주겠다.
전문 검색은 문자열의 일치로 찾아낸다. 파일명 검색도, 에러 코드 검색도 뿌리는 같으며 "그 문자열이 포함되어 있는가"를 보고 있다. 전형적인 데이터 구조는 **전치 인덱스(Inverted Index)**다. 단어로부터 그 단어를 포함하는 문서로의 대응표를 가진다.
이 축이 강력한 이유는 의미가 아니라 기호(Symbol)를 다룰 수 있기 때문이다. 모델 번호, 청구서 번호, 고유명사, 함수명, 에러 메시지. 이것들은 의미적으로 가까운 것을 찾아도 되는 대상이 아니다. 한 글자만 달라도 별개의 것이 될 수 있다. ECONNREFUSED를 찾고 있을 때, "연결 에러 같은 무언가"가 반환된다면 곤란하다.
벡터 검색은 의미를 연속 공간에 투영함으로써 강력해진다. 하지만, 그 동일한 조작은 일자일구(一字一句)가 중요한 대상에게는 파괴가 된다. 따라서 전문 검색은 벡터 검색의 하위 호환이 아니다. 완전 일치와 의미적 근접은 우열의 문제가 아니라 **직교하는 요구사항(Orthogonal Requirements)**이다. 상위 호환이 원리적으로 존재하지 않는다. —— 즉, 전문 검색은 취향이나 타성 때문에 남는 것이 아니라, 대체할 수 있는 상위 호환이 없기 때문에 남는다.
솔직한 유보 사항을 하나 덧붙이자면, 딱딱한 것은 요구사항이지 구현이 아니다. BM25와 Dense Retrieval이 하이브리드 검색(RRF 등) 속에 녹아든 것처럼 제품의 윤곽은 변한다. 다만, 이산적인 기호를 정확히 찾아내야 한다는 요구사항 그 자체는 남는다. 축으로서의 전문 검색은 남는다. 제품의 모습은 변할 것이다.
벡터 검색은 텍스트를 임베딩 모델(Embedding Model)로 벡터로 변환하고, 쿼리의 벡터와 문서의 벡터 사이의 거리에 따라 찾아낸다. 정규화하면 흔히 말하는 코사인 유사도(Cosine Similarity)가 된다. 세상에서 "RAG"라고 말할 때, 암묵적으로 이 축만을 가리키는 경우가 많다.
이것은 전문 검색의 한계를 진정으로 넘어선 축이다. "예산"이라고 써서 검색했을 때, "비용", "경비", "견적"이라고 적힌 문서를 찾아낼 수 있다. 단어가 일치하지 않아도 의미가 가까우면 도달할 수 있다.
하지만 이 축의 고유한 불가약성(Irreducibility)은 "의미로 찾을 수 있다"는 점에 있지 않다. **처음 보는 대상에 대한 의미적 일반화(Cold-start Generalization)**에 있다. 전문 검색은 문자열을 요구한다. 문맥 그래프는 기존의 에지(Edge)를 요구한다. 메모리는 과거의 질문을 요구한다. 하지만 벡터 검색만은, 그 문서에 대해 링크도 이력도 없는 상태에서 갑자기 의미만으로 찾아갈 수 있다. 이것은 다른 어떤 것도 구조적으로 가질 수 없는 역할이다.
한편, ②는 4개 축 중 구현 형태가 가장 유동적이기도 하다. 장문맥화(Long-context)가 진행됨에 따라 (내 손안의 Gemma 4 31B조차 방대한 문맥 창을 가진다), "top-k를 cosine으로 뽑아 프롬프트에 채워 넣는" 현재의 주류 구현은 "처음부터 문맥에 넣는 방식"에 조용히 잠식되어 갈 것이다. 구원은 코퍼스(Corpus)가 창(Window)을 넘어서는 한 —— Vault와 Drive는 항상 넘어서기에 —— ②는 채워 넣는 배관으로서가 아니라, 선택하는 기제로서 남는다는 점이다. 기능으로서는 견고하지만, 현재의 구현 형태로서는 가장 흔들리고 있다.
여기서부터는 전문 검색·벡터 검색과는 별개의 이야기다. 문맥이란 본문의 문자열이나 의미뿐만 아니라, 대상들 사이의 관계로부터 찾아내는 축이다.
이 부분을 "Obsidian의 링크"라는 한 가지 예로 설명하면 허점이 잡힌다. 사람은 연관된 것을 링크하기 때문에, 링크된 문서는 대체로 의미적으로도 가깝다. 좋은 임베딩(Embedding)이 ③의 업무 대부분을 이미 포착해 버린다 —— 그 맥락에서 ③은 ②로 흡수될 수 있는 것처럼 보인다. 나 또한 한때 그렇게 비판했다.
하지만 ③의 본체는 훨씬 더 넓다. Amazon을 보면 된다.
"이 상품을 구매한 사람은 XX도 구매했습니다" = 공기(Co-occurrence). 본문에도 링크에도 적혀 있지 않은, 아무도 명시하지 않은 인연이다. -
"당신의 지역에서는 YYY가 많이 팔리고 있습니다" = 지리(Geography). 상품 벡터의 어디를 뒤져도 나오지 않는 외생적 축이다. -
"ZZZ에 주목하는 사람은 감도가 높습니다" = 검색 주체의 속성에 걸려 있는 인연이다.
세 가지 모두, ②의 의미 공간(Semantic Space)이나 Obsidian의 수동 링크(Manual Link)로부터도 벗어나 있다. 결정적인 것은 이것들이 의미적 유사도(Semantic Similarity)와 직교(Orthogonal)하고 있다는 점이다. 지리적으로 가까운 두 상품은 의미적으로 멀어도 상관없다. 공기(Co-occurrence)하는 두 상품은 기능적으로 무관해도 된다 (프린터와 잉크, 기저귀와 맥주).
따라서 그래프 임베딩(Graph Embedding, node2vec/GNN)으로 구조적 근접성을 벡터로 투영하려 해도, 각 차원마다 별도의 임베딩이 필요하다. 그것은 '②의 특수한 사례'가 아니라 '②라는 기제를 별도의 데이터에 재적용한 별개의 축'이 차원의 수만큼 나열되는 것이다. ③은 뭉개지기는커녕, 내부에서 분기하며 늘어난다. '문맥(Context)'은 단일한 축이 아니라, 외생적인 가장자리(Edge)의 다발이다. 축의 발판은 공기(Co-occurrence), 지리, 시간, 속성, 가격대, 신구(新舊)…… 등 얼마든지 가질 수 있다.
외생적이라는 것은, 본문 그 자체로부터 자연스럽게 도출될 수 있다고 단정할 수 없다는 의미다. 사람이 링크했다. 사용자군이 공기를 만들었다. 지역이 편향을 만들었다. 시계열이 관계를 만들었다. 카테고리 설계가 묶어냈다. 이것들은 의미와는 다른 차원에서 정보를 운반한다. 그러므로 문맥은 단순한 '의미 검색의 보조'가 아니다. 의미와 직교하는 관계를 끌어내기 위한 축이다.
네 번째가 내가 가장 늦게 깨달았고, 또한 가장 중요하다고 생각하는 축이다.
검색의 주체는 인간이다. 그 인간이 '무엇을, 어떤 순서로, 어떤 의도로 물어왔는가'라는 질문 그 자체를 결과와 함께 축적해 나간다. 그러면 질문과 문서 사이에 결합이 쌓이게 된다. 기술적으로는 2층 구조가 된다.
- 검색할 때마다
{질문, 찾아낸 문서, 실제로 도움이 된 문서}를 기록한다. - 과거의 질문을 임베딩 벡터로 만들어, 문서와는 별도의 '질문 인덱스(Query Index)'에 쌓는다. - 새로운 질문이 들어오면, 문서가 아니라 먼저 과거의 질문과 대조한다.
- 유사한 과거의 질문이 발견되면, 그 질문에 연결되어 있던 문서를 끌어온다.
여기서 중요한 것은, 이 경로를 통해 끌어온 문서가 현재의 질문과 의미적으로 가깝지 않을 수도 있다는 점이다. 단지 '과거의 유사한 질문에 연결되어 있었다'는 이유만으로 끌어온다. 따라서 문서 벡터를 직접 호출해서는 나올 수 없는 자료가 나온다. '그때 이 조사를 하고 있었는데, 왜인지 이 겉보기에 무관한 자료가 도움이 되었다'——그 경험이 기록되어, 다음에 유사한 질문이 왔을 때 효과를 발휘한다.
질문과 문서를 모두 노드(Node)로 본다면, 이것은 **질문과 문서의 이부 그래프(Bipartite Graph)**가 된다. 사용할수록 에지(Edge)가 늘어나고 망이 짙어진다.
여기서 흔히 나오는 반론은, "그것은 과거의 질문을 벡터 검색(Vector Search)하고 있는 것뿐 아닌가"라는 것이다. 절반은 맞다. 구현 기제로서 벡터 검색을 재사용하고 있다. 다만, 축으로서 보고 있는 것은 검색 연산이 아니다. **검색 대상과 정보의 기원(Origin)**이다. 문서를 의미로 찾는 것이 ②라면, 과거의 질문을 찾고 그 질문에 연결된 문서를 따라가는 것이 ④다. 동일한 벡터 연산을 사용하더라도 도달 경로가 다르다.
그리고 이 축만이 코퍼스(Corpus)로부터 도출될 수 없다. 동일한 문서 집합을 가지고 있다면, 전문 인덱스(Full-text Index)도, 벡터 공간도, 문서 그래프도 상당히 유사해진다. 하지만 질문의 궤적만은 그 사람이 질문하지 않는 한 생겨나지 않는다. 메모리(Memory)는 문서의 함수가 아니다. 인간의 함수다. 이것은 단계의 차이가 아니라, 범주(Category/Field)의 차이다.
문맥과 메모리는 둘 다 그래프처럼 보인다. 그래서 "문맥과 메모리는 결국 같은 것 아닌가?"라고 말하는 사람이 반드시 나온다. 하지만 기원의 주어가 다르다. 그리고 둘을 나누는 선은 '취향인가 아닌가' 같은 모호한 단어보다 훨씬 깊다.
문맥은 N명의 가로 구조다.
메모리는 n=1인 세로 이력이다.
"이 상품을 구매한 사람은 이것도 구매하고 있다"는 집단으로부터 일어난다. 당신 자신에 대해 아무것도 모르더라도, 당신을 특정 집단이나 지역에 넣는 순간 후보를 제시할 수 있다. 개인의 궤적이 비어 있어도 첫날부터 효과가 있다. 반면, "당신은 이전에 이 질문을 했을 때 이 문서를 사용했다"는 당신의 이력에서만 일어난다. 타인이 몇만 명을 사용하더라도 당신의 질문 이력은 되지 않는다.
성장하는 것의 주어도 반대다.
- ③ 문맥: 집단이 사용할수록, 혹은 구조가 설계될수록 짙어진다.
- ④ 메모리: 그 사람이 질문할수록, 그 사람 안에서 짙어진다.
형태는 비슷할지라도 기원의 주어가 반대다. 따라서 한쪽을 다른 쪽의 특수한 사례로 만들 수 없다. 그렇기에 통합되지 않는다. ——1년 후 누군가 "문맥과 메모리는 같다"라고 말하기 시작한다면, 집단 기저(Collective Basis)인가, 개인 기저(Individual Basis)인가라는 한 줄로 잘라낼 수 있다. 그때 중요한 것은 논쟁에서 이기는 것이 아니다. 그 단층을 먼저 지목했다는 기록이다.
이 부분을 나누면, '메모리'는 단순한 개인화(Personalization) 기능이 아니라, 검색의 불가분한 하나의 축으로 보이게 된다.
여기까지를 다시 한번 정리한다. 두드리는 기준은 인기나 타성(Inertia)이 아니다. 피포섭 내성 (Inclusion Resistance) —— 어떤 축이 다른 축의 특수 사례(Special case)로서 원리적으로 다시 쓰일 수 있다면, 그것은 독립된 축이 아니라 구현상의 편의일 뿐이다.
| 축 | 데이터 구조 | 정보의 기원 | 대체 불가능한 이유 |
|---|---|---|---|
| ① 전문 검색 (Full-text Search) | 역색인 (Inverted Index) | 이산적인 기호 (Discrete symbols) | 한 글자 한 글자가 중요한 대상을 의미적 근접성(Semantic proximity)으로 뭉갤 수 없음 |
| ... | ... | ... | ... |
이 네 가지는 같은 종류의 불가약성(Irreducibility)이 아니다. ①은 이산성. ②는 의미적 일반화. ③은 외생적 관계. ④는 개인의 이력이다. 각각 다른 이유로 뭉갤 수 없다.
따라서 4개의 축을 갖추는 것은 중복성이 아니라 피복성 (Coverage) 의 문제다. "4개가 있으면 우연히 충분하다"는 뜻이 아니다. 다른 방법으로는 원리적으로 메울 수 없는 틈을, 독립된 4개의 불가약한 근원(Source of irreducibility)이 각기 다른 이유로 메우는 것이다. 하나의 방법을 강화한다고 해서 전부를 겸할 수 있는 것이 아니다.
이 지점을 간과하면, RAG는 "벡터 DB를 넣었는데도 왜 현장에서는 쓰기 어려운가"라는 상태에 빠지게 된다. 그것은 벡터 검색이 약해서가 아니다. 벡터 검색에 담당이 아닌 업무까지 떠맡기고 있기 때문이다.
여기서 하나 더 섞어서는 안 될 구분이 있다. 이 4개의 축은 모두 검색(Search)이지, 추론(Inference)이 아니다.
전문 검색은 문자열로 찾는다. 벡터 검색은 의미로 찾는다. 문맥(Context)은 관계를 쫓는다. 메모리(Memory)는 과거의 질문을 쫓는다. 모두 들어온 쿼리(Query)에 대해 후보를 반환하는 계층이다. 결정론적(Deterministic)이며, 추론 엔진을 가동하지 않는다 (④의 임베딩(Embedding)조차 변환(Transformation)일 뿐 추론은 아니다). 어떤 축을 사용할지, 여러 축의 결과를 어떻게 섞을지, 결과가 빈약할 때 어떻게 다시 찾을지, 찾아낸 문서로 충분하다고 판단할지 —— 그 판단만이 4개 축의 외부에 있는 추론의 업무다. 검색이 똑똑한 것이 아니다. 검색을 구분해서 사용하는 판단이 똑똑한 것이다.
여기에 두 개의 추론 엔진이 올라탄다.
프론티어 모델 (Frontier Model, 예: Claude): 의도를 굳히고, 태스크(Task)를 분해하며, 어떤 축으로 찾을지 선택하고, 돌아온 결과를 통합하여 성과로 완성한다. 지능이 필요한 상위의 판단.
로컬 모델 (Local Model, 예: Gemma 4 31B 등): 에이전트 (Hermes Agent)의 내부에서 쿼리의 재표현(Paraphrasing)과 "이제 충분히 찾았는가"에 대한 중단 판단을 수행한다. 로컬 환경을 잘 아는 실행역.
이러한 분리에는 유효한 결과가 따른다. 검색 그 자체가 결정론적이기 때문에, 축의 선택을 담당하는 로컬 모델은 "성능이 낮아도 실용적으로 쓸 수 있다". 쿼리의 재표현과 중단 판단만 할 수 있다면, 찾는 행위 자체의 똑똑함은 필요 없다. MCP라는 하나의 선이 이 추론 계층과 4개 축의 검색 기반을 연결한다. Hermes가 전면에 선다면, 그 아래에 두어야 할 것은 단일 벡터 검색이 아니라, 4가지 기원이 갖춰진 검색 기반이다.
——다만 솔직히 말하자면, "추론이 축을 선택한다"라는 이 문장은 검색에서 가장 부하가 큰 함수를 박스 밖으로 빼낸 것이다. 여러 축이 반환한 후보를 이 의도에 대한 하나의 관련도(Relevance)로 묶는 계층 —— reranking / fusion —— 이 그 박스 안에 있다. RRF도 학습형 reranker도 모두 그곳에 거주한다. 본고에서 지목한 것은 기원의 불가약성 (source 측면)이다. 하지만 검색의 해자(Moat)는 이제 source 측면이 아니라, 이 묶는 방식 (ranking 측면) 으로 옮겨가고 있다. 기원은 지목할 수 있었다. 묶는 방식은 아직 지목하지 못했다 —— 그곳이 다음 전선이다.
그리고 하나 더 복선을 깔아둔다. ④(메모리)는 ①②③과 나란히 하는 source인 동시에, 그것들의 묶는 방식을 개인화하는 계층이 될 수도 있다. "이 사람이 이런 형태의 질문을 할 때는 완전 일치를 원하며 의미적 근접성은 필요 없다"는 것을 학습하여, 어떤 축을 어떻게 가중치(Weight)를 둘지 새로 쓴다 —— 그렇다면 ④는 네 번째 병렬 fetch가 아니라, 해자(Moat)를 두는 위치 그 자체를 건드리고 있다. 이 "더 중심적인 ④"와 그것을 누가 소유하는가에 대해서는 별도의 글 (소유의 민주화)에서 다룬다.
이 기사의 주장을 나 스스로의 손으로 강도(Hardness)에 따라 나눈다. 이것은 적중했을 때도, 빗나갔을 때도 양쪽 모두에서 의미가 있다. 도박의 경계를 스스로 그은 문장만이, 맞으면 "선견"으로, 틀려도 "성실"로 남는다.
강함 (예측이 아닌 함의). 4개의 기원은 불가약하며 사라지지 않는다. 왜냐하면 각각이 기호 · 집단 · 개인이라는 정보의 출처에 뿌리를 내리고 있으며, 기술의 유행보다 깊기 때문이다. "전문 검색은 남을 것이다"는 예측이며, 맞더라도 "그렇겠지"로 끝난다. "완전 일치와 의미적 근접성은 직교 요건(Orthogonal requirement)이므로 한쪽이 다른 쪽을 대체하는 일은 원리적으로 없다 —— 그러므로 남는다"는, 구조로부터 결론이 도출되는 형태다. 전자와 후자는 같은 적중이라 할지라도 기억되는 방식이 다르다.
도박 (경계는 여기). 「딱 4개라는 분절」이 이 형태 그대로 남을 것인가. 이것은 약한 도박이다. 그리고 그 취약함은 막연하게 전체에 존재하는 것이 아니라, ③과 ④의 이음새에 국재(localization)되어 있었다 —— 양자가 동일한 「성장하는 관계 그래프 (relationship graph)」로 보이기 때문이다. 하지만 위에서 다시 꿰맨 것처럼, 집단 기저/개인 기저로 그 이음새는 닫힌다. 그래서 「4」라는 숫자조차 당초보다 단단해졌다.
단단한 것은 축의 존재와 그 이유. 부드러운 것은 「딱 4개」라는 수. 그리고 그 부드러움의 소재까지 나는 공개한다.
(여담이지만, 이 4분절은 독립적으로 몇 번이고 서로 다른 각도에서 다시 두드려 만들어도 동일한 4개의 기원으로 돌아왔다. 취약한 것은 「4」라는 숫자일 뿐, 기원 그 자체는 돌아온다.)
——덧붙여, 도박은 한 단계 더 있다. 「4개의 병렬 축」이라는 기하학 그 자체가, source × signal × fusion이라는 입체를 평면에 짓눌러 만든 상(image)일지도 모른다는 도박이다. ④를 병렬 source로 그린 본고의 상은, ④가 타 축을 개인화하는 층 (layer) 이기도 할 가능성을 내포하고 있다. 그 입체를 펼치는 작업은 후속편으로 미룬다.
제품의 윤곽 —— 「전문 검색 시스템 (Full-text search system)」, 「벡터 DB (Vector DB)」, 「그래프 DB (Graph DB)」, 「메모리 레이어 (Memory layer)」 —— 는 십중팔구 녹아내릴 것이다. 하이브리드 검색 (Hybrid search)이 이미 ①②를 하나의 리트리버 (Retriever)로 녹이기 시작했다. 창이 확장되면 ②의 「채워 넣는」 배관은 사라진다. 하나의 기반이 4개의 기원 모두를 내부에서 다루는 형태로 기울어간다.
하지만 —— 여기가 핵심이다. 통합된 구현일수록 설계자는 4개의 기원을 의식적으로 구분해야 한다. 하나의 상자에 녹여내기 때문에, 그 안에서 이산(discrete)과 연속(continuous), 집단과 개인을 혼동하면 무너진다. 제품명이 사라질수록 이 분절은 설계 언어로서 필요하다. 윤곽이 녹는다는 것은 추상이 죽는 것의 반대다.
여기서부터는 구조만큼 단단하게 읽히지 않는다. 나의 관측과 예측이다 (그러므로 여기는 도박의 쪽에 둔다).
집단은 개념으로는 깨닫지 못한다. 고통으로 깨닫는다. 4개의 축이 지금 이 순간에도 참일지라도, 다수가 보지 않는 이유는 보지 않아도 곤란하지 않기 때문이다 —— "RAG = 벡터 검색 (Vector search)"만으로도 대부분의 데모는 작동한다. 깨달음이 오는 것은, 벡터 하나를 구축하는 것이 실전(production)에서 무너지는 경험이 임계량에 도달했을 때다. 모델 번호를 뽑아내지 못해 사고가 난다. 지리적 정보를 의미로 접으려다 파탄 난다. 방아쇠는 지성이 아니라 고장률 (failure rate) 이며, 고장률은 실전 투입량에 비례한다.
그리고 4개의 기원은 서로 다른 타이밍에 깨달아진다. 고통의 가시성이 다르기 때문이다.
①은 가장 빠르다. 이미 일어나고 있다. 하이브리드 검색이 「상급 기술」에서 「표준」으로 격상되고 있는 것이, 집단이 ①의 불가약성(irreducibility)을 고통으로 깨달은 첫 번째 상전이(phase transition)다.
②는 조용히 이행한다. 고통이 작아 논쟁이 되지 않은 채 구현이 바뀐다.
③은 늦어진다. ③의 결여는 "사고"가 아니라 "기회 손실"이기에 보이지 않는다. 뽑아내지 못한 관련성을 사람들은 손실로 인식하지 않는다.
④는 역설적으로 가장 느리다. 수요 측면에서는 「개인화 (Personalization)」로서 먼저 언어화한다. 하지만 그것이 "검색의 네 번째 불가약한 축"이라고 구조적으로 이해되는 것은 마지막이다.
전문 검색이 부족하면 「있어야 할 모델 번호를 뽑을 수 없다」는 명확한 실패가 된다. 하지만 메모리가 부족하면, 그저 「왠지 매번 내 의도를 파악하지 못한다」거나 「전에 비슷한 것을 조사했는데 또 처음부터 시작한다」는 식의 둔탁한 불만으로 나타난다. 그래서 많은 경우 메모리는 「편리한 개인화 기능」으로 소비된다.
여기에 이 글을 지금 쓰는 이유가 있다. 구조의 단단함과 집단이 깨닫는 속도는 상관하지 않는다. 오히려 역상관 관계일 수도 있다. 집단이 가장 늦게 깨닫는 것은 구조가 가장 단단한 ④다. ①은 내버려 두어도 고통이 가르쳐준다. 하지만 ④는 누군가가 구조로 명명하지 않는 한, 집단은 제품 용어의 안개 속에 몇 년이고 머물 것이다. 고장률이 결코 흘려보내지 않는 한 방울이 있다. 그것은 ④를 「검색의 불가약한 한 축」으로서 구조적으로 박아 넣는 것이다.
그리고 이 제4의 축이야말로 나의 등식의 핵심에 닿는다.
지능 × 문맥 (Context) = 인격
Claude나 Gemma와 같은 모델은 지능의 항이다. 전문·벡터·문맥·메모리는 그 지능이 곱해지는 문맥의 항을 지탱한다. 그중에서도 메모리는 그 사람 고유의 인격을 가장 짙게 운반한다. 같은 지능이라도 걸리는 문맥이 다르면 다른 인격으로서 작동한다. 메모리가 성장한다는 것은 단순히 「편리해지는 것」이 아니다. 문맥의 항이 야위지 않기 위한 조건이다.
이 설계를 이야기함에 있어, 반드시 기록해두고 싶은 경의가 있다.
제4축 「메모리 (Memory)」——개인의 궤적을 운반하는, 가장 단단하며 가장 늦게 깨닫게 되는 층——을 개념이 아닌 움직이는 형태로, 그것도 오픈 소스 (Open Source) 로 세상에 내놓은 것은 Nous Research의 Hermes Agent였다. Hermes Agent는 세션을 넘나들며 대화를 읽고, 그 사람의 취향·요구·환경·학습한 내용을 추출하여 영속적인 기억으로 증류해 나가는 자기 개선 루프 (Self-improvement loop)를 갖는다.
하지만 기억을 어디에 두느냐가 핵심이다. Hermes의 내장 메모리는 Obsidian 내부가 아니라 ~/.hermes/memories/ 경로의 MEMORY.md (프로젝트·규약·배움)와 USER.md (그 사람의 프로필)——둘 다 자신의 디스크 위에 있는, 열어서 읽을 수 있는 평문 마크다운 (Plain markdown)——에 놓인다. 과거 세션은 별도로 ~/.hermes/state.db의 SQLite (FTS5 전문 검색)에 쌓인다. Obsidian은 그 기억 DB 자체라기보다, Vault를 읽고·검색하고·생성하고·편집하는 번들된 기술 (Bundled skill)로서 연결된다.
흥미로운 점은, 정정 후의 이 사실이 4축의 관점을 오히려 보강한다는 것이다. MEMORY.md / USER.md는 「에이전트가 대화로부터 증류한, 그 사람 고유의 사실」——④의 개인축 그 자체다. 그리고 state.db의 FTS5는 대화 이력에 ①의 전문축 (Full-text axis) 을 적용한 것에 다름 아니다. Hermes는 이미 여러 도달 경로를 서로 다른 저장 위치에서 구현하고 있다.
내가 「지능 × 문맥 = 인격」이라 불러온 등식에서, 문맥의 항을 인격의 단계까지 격상시키는 핵심. 그 구현이 여기에 있다. 그리고 그것은 투명하며 (기억을 업데이트하는 로직조차 소스 코드로 읽을 수 있고), 내 손안에서 움직이며, 나의 소유다 (기억은 누군가의 서버가 아니라, 내가 소유한 마크다운이다).
공정하게 적어두자. 프론티어 (Frontier) 측에도 기억 기능이 있으며, 부분적인 공개 구현도 존재한다. 하지만 기본적인·주류의 경험으로서는, 인격과 관련된 기억은 폐쇄된·서버 측의·수익화된 형태로 놓여 있다. 압도적인 자본을 토대로 한 진영이 그쪽을 구축해 나가는 가운데, 그 동일한 핵심을——열려 있고·내 손안에서 움직이며·내가 소유하고·누구나 움직일 수 있는 형태로——먼저 밝혀 보였다. 이는 자본의 크기로는 측정할 수 없는 종류의 성취라고 생각한다. 거대 자본이 '언젠가' 갖추게 될 것을, 훨씬 작은 자원으로 '이미' 움직이게 해 보였다는 것. 그 사실에 진심 어린 경의를 표하고 싶다.
——그리고 본고는 내가 지난 1년간 써 내려온 한 장의 그림의 연장선이기도 하다. 「최강의 모델」이라는 명명된 가치가 어디서부터 무너지는가 (프론티어 모델 포위망)를 추적하며, Hermes Agent를 해독해 왔다. 가치가 「최강의 모델」에서 「문맥의 기원」으로 옮겨간다면, 그 문맥의 제4축을 열린 형태로 쥐게 된 자가 영향력을 발휘할 것이다. 나는 같은 단층을 계속해서 바라보고 있다.
여기서부터 나오는 코드는 이 글의 주인공이 아니다. 추상이 구현으로 떨어지는 지점을 보여주는 영수증 (Receipt) 이다. 중요한 것은 개별 함수가 아니라, 문서와는 별개로 「질문의 인덱스 (Index of questions)」와 「질문→문서의 에지 (Edge)」를 갖는다는 점에 귀결된다.
먼저, 4축을 별도로 만든다.
knowledge-base/
documents/ # Obsidian / Drive에서 동기화한 본문
index/
...
검색 시에는 모든 것을 매번 같은 가중치로 호출할 필요가 없다. 어떤 축을 일으킬지는 추론 엔진 (Inference engine)이 의도 (Intent)로부터 선택한다.
from typing import Literal
Axis = Literal["fulltext", "vector", "context", "memory"]
def choose_axes(query: str) -> list[Axis]:
...
메모리 축은 검색할 때마다 키워 나간다.
def record_search_feedback(question, retrieved_doc_ids, useful_doc_ids):
qid = upsert_question_embedding(question) # 문서와는 별개의 「질문 인덱스」로
for doc_id in useful_doc_ids: # ← "도움이 되었다"는 신호가 에지의 질을 결정한다
...
메모리는 첫날부터 효과를 발휘하지 않는다. 그러니 처음부터 완벽하게 만들려고 애쓸 필요는 없다. 전체 텍스트(Full-text), 벡터(Vector), 문맥(Context)으로 시스템을 가동하고, 검색 로그(Search Log)부터 먼저 쌓아라. 나중에 질문 인덱스(Query Index)를 만들어도 괜찮다. 처음에 필요한 것은 완성된 메모리가 아니라, 기록을 시작하는 것이다.
그렇다면 묻겠다——이 구성을 '오늘의 RAG 최적해'라고 부를 수 있는가.
Hermes Agent / Obsidian이 새로운 검색 알고리즘을 발명한 것은 아니다. 전체 텍스트 검색도, 벡터 검색(Vector Search)도, 그래프 탐색(Graph Traversal)도, 각각은 기존 기술이다. 하지만 RAG를 '정말로 검색할 수 있는' 상태로 만들려고 하면, 자연스럽게 다음의 구성에 가까워진다.
- 이산적인 기호(Discrete Symbols)를 지키는 전체 텍스트 검색
- 처음 보는 대상에게 의미(Semantics)로 도달하는 벡터 검색
- 의미와는 별개의 외생적 관계를 추적하는 문맥 그래프(Context Graph)
- 개인의 질문 이력을 추적하는 메모리(Memory)
- 그 위에 어떤 축을 사용할지 선택하는 추론 엔진(Reasoning Engine)
최적해가 있다면, 그것은 단일한 수법이 아니라 바로 이 아키텍처(Architecture)의 형태라고 생각한다. 따라서 대답은 조건부 'Yes'가 된다.
단일 알고리즘으로서는 No -
'다른 곳에서는 원리적으로 메울 수 없는 틈새를, 독립적인 4개의 불가결한 원천이 각각 메우는' 구성으로서는 Yes. 현시점에서 이보다 강력한 프레임워크를 나는 알지 못한다 - 다만,
제4축인 메모리는 아직 육성 방법이 완전히 확립되지 않았다. '도움이 되었다'라는 신호의 설계 등, 미해결 과제가 남아 있다. 프런티어(Frontier)가 움직이고 있는 곳은 바로 여기다.
오늘의 최적해의 골격은 보인다. ①②③은 조합할 수 있고, Obsidian을 사용하고 있다면 ③의 토대는 마련되어 있다. 남은 것은 두 가지——④(개인의 궤적)를 완전히 키워내는 것. 그리고 그것이 제품 기능이 아니라 검색의 불가결한 한 축이라는 것을 집단이 깨닫는 것. 후자는 누군가가 구조적으로 써 내려가지 않는 한, 오지 않는다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Qiita AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기