{"title":"의미론적 검색 (임베딩)","slug":"semantic-search","category":"concepts","summary":"벡터 임베딩을 사용한 개념적 메모리 검색 — 키워드뿐만 아니라 의미로 찾습니다.","audience":["human","llm"],"tags":["concept","semantic","embeddings","vector-search"],"difficulty":"advanced","updated":"2026-06-27","word_count":474,"read_minutes":2,"lang":"ko","translated":true,"requested_lang":"ko","content_markdown":"\n# 의미론적 검색 (임베딩)\n\nSynapse는 벡터 임베딩을 사용한 의미론적 검색을 지원합니다. FTS5 (키워드\n매칭)와 달리 의미론적 검색은 키워드가 일치하지 않더라도 **의미**로\n메모리를 찾습니다.\n\n## 작동 방식\n\n```\n1. Memory stored → embedding generated → vector stored\n2. Search query → embedding generated → vector compared\n3. Cosine similarity → top N results returned\n```\n\n### 임베딩이란?\n\n임베딩은 텍스트의 수치적 벡터 표현입니다. 유사한 의미를 가진 텍스트는\n유사한 벡터를 가집니다. Synapse는 각 메모리의 콘텐츠에 대해 벡터 (예:\n1536차원)를 생성합니다.\n\n### 코사인 유사도\n\n의미론적으로 유사한 메모리를 찾기 위해 Synapse는 쿼리 벡터와 각 메모리\n벡터 간의 코사인 유사도를 계산합니다. 유사도가 높을수록 더 관련성이\n높습니다.\n\n## 의미론적 검색 사용 시기\n\n### 의미론적 검색을 사용할 때:\n\n- 저장된 것과 다르게 설명된 \"X에 대한 메모리\"를 원할 때\n- FTS5가 결과를 반환하지 않을 때 (키워드 매칭 없음)\n- 개념적 그룹화를 원할 때 (예: 일부가 \"release\"라고 말하더라도 모든 \"deployment\" 메모리)\n- 쿼리가 질문일 때: \"인증은 어떻게 처리합니까?\"\n\n### FTS5를 사용할 때:\n\n- 정확한 키워드를 알 때\n- 불린 로직 (AND, OR, NOT)이 필요할 때\n- 서브밀리초 응답이 필요할 때\n- 구문 매칭을 원할 때\n\n## 엔드포인트\n\n### GET /memory/semantic-search\n\n```bash\ncurl -H \"Authorization: Bearer YOUR_MIND_KEY\" \\\n     \"https://synapse.schaefer.zone/memory/semantic-search?q=container+orchestration\"\n```\n\n응답:\n\n```json\n{\n  \"results\": [\n    {\n      \"id\": \"mem_001\",\n      \"category\": \"project\",\n      \"key\": \"project_synapse_deployment\",\n      \"content\": \"Synapse deployed using Docker Swarm on vps1...\",\n      \"tags\": [\"docker\", \"swarm\", \"deployment\"],\n      \"similarity\": 0.89\n    },\n    {\n      \"id\": \"mem_042\",\n      \"category\": \"fact\",\n      \"key\": \"kubernetes_cluster\",\n      \"content\": \"We use Kubernetes for production orchestration...\",\n      \"tags\": [\"kubernetes\", \"orchestration\"],\n      \"similarity\": 0.84\n    }\n  ]\n}\n```\n\n## 예시\n\n### 배포 메모리 찾기\n\n```bash\n# FTS5 might miss some — semantic catches all\ncurl .../memory/semantic-search?q=deployment+process\n```\n\n\"deployment\", \"release\", \"publishing\", \"rolling out\" 등에 대한 메모리를\n반환합니다.\n\n### 인증 패턴 찾기\n\n```bash\ncurl .../memory/semantic-search?q=how+do+users+log+in\n```\n\nlogin, auth, JWT, session management, OAuth 등에 대한 메모리를 반환합니다.\n\n### 유사한 메모리 찾기\n\n```bash\n# Find memories similar to a specific one\ncurl .../memory/related/mem_001\n```\n\n(공유 태그 및 임베딩 벡터를 통해) 의미론적 유사도를 사용합니다.\n\n## 임베딩 생성\n\n### 임베딩은 언제 생성되나요?\n\n- **메모리 저장 시** — 임베딩 서비스가 구성된 경우, 동기적으로 임베딩 생성\n- **배치 생성** — `POST /memory/embed-batch`가 임베딩이 없는 메모리의 임베딩 생성\n- **비동기 업데이트** — 콘텐츠가 업데이트되면 임베딩 재생성\n\n### 임베딩 제공자\n\nSynapse는 구성 가능한 임베딩 제공자를 지원합니다:\n\n- **OpenAI** (`text-embedding-3-small`, `text-embedding-3-large`)\n- **로컬 모델** (Ollama 등을 통해)\n- **사용자 정의** (임베딩 인터페이스 구현)\n\n환경 변수로 구성:\n\n```bash\nEMBEDDINGS_PROVIDER=openai\nEMBEDDINGS_API_KEY=sk-...\nEMBEDDINGS_MODEL=text-embedding-3-small\n```\n\n### 배치 생성\n\n임베딩이 누락된 메모리가 많은 마인드의 경우:\n\n```bash\n# Generate embeddings for up to 100 memories\ncurl -X POST https://synapse.schaefer.zone/memory/embed-batch \\\n  -H \"Authorization: Bearer YOUR_MIND_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"limit\": 100}'\n\n# Check progress\ncurl -H \"Authorization: Bearer YOUR_MIND_KEY\" \\\n     https://synapse.schaefer.zone/memory/embed-batch-status\n```\n\n## 성능\n\n| 작업 | 지연 시간 |\n|-----------|---------|\n| 임베딩 생성 (OpenAI) | 100-200ms |\n| 의미론적 검색 (1k 메모리) | 50-100ms |\n| 의미론적 검색 (10k 메모리) | 200-500ms |\n| 배치 생성 (100 메모리) | 10-20s |\n\n> [!NOTE]\n> 의미론적 검색은 벡터 계산으로 인해 FTS5보다 느립니다. 알려진 키워드에는\n> FTS5를, 개념적 쿼리에는 의미론적 검색을 사용하십시오.\n\n## 제한 사항\n\n### 임베딩 비용\n\nOpenAI를 사용하는 경우, 임베딩 생성에 비용이 듭니다 (text-embedding-3-small의\n경우 1M 토큰당 ~$0.02). 평균 100 토큰인 10,000개 메모리의 경우\n~$0.02 — 무시할 수 있는 수준입니다.\n\n### 콜드 스타트\n\n임베딩이 구성되기 전에 저장된 메모리는 임베딩이 없습니다. `POST\n/memory/embed-batch`를 실행하여 백필하십시오.\n\n### 제공자 의존성\n\n임베딩 제공자가 다운된 경우, 의미론적 검색은 정상적으로 실패합니다 (빈\n결과 또는 오류 반환). FTS5는 여전히 작동합니다.\n\n## 임베딩을 사용할 수 없는 경우\n\n임베딩 서비스가 구성되지 않은 경우:\n\n- `GET /memory/semantic-search`가 503 Service Unavailable 반환\n- `POST /memory`는 여전히 작동 (임베딩만 생성 안 됨)\n- FTS5 검색은 여전히 작동\n\n## 모범 사례\n\n> [!TIP]\n> - **개념적 쿼리에 의미론적 검색 사용** — \"X를 어떻게 처리합니까?\"\n> - **특정 용어에 FTS5 사용** — \"docker swarm\"\n> - **정기적으로 임베딩 백필** — `POST /memory/embed-batch`\n> - **제공자 상태 모니터링** — 의미론적 검색은 이에 의존\n> - **태그와 결합** — 의미론적 + 태그 필터가 결과를 좁힘\n\n## 다음 단계\n\n- [FTS5 검색](/docs/concepts/fts5-search)\n- [Memory API](/docs/api/memory)\n- [아키텍처](/docs/concepts/architecture)\n","content_html":"<h1>의미론적 검색 (임베딩)</h1>\n<p>Synapse는 벡터 임베딩을 사용한 의미론적 검색을 지원합니다. FTS5 (키워드\n매칭)와 달리 의미론적 검색은 키워드가 일치하지 않더라도 <strong>의미</strong>로\n메모리를 찾습니다.</p>\n<h2>작동 방식</h2>\n<pre><code class=\"hljs language-plaintext\">1. Memory stored → embedding generated → vector stored\n2. Search query → embedding generated → vector compared\n3. Cosine similarity → top N results returned</code></pre><h3>임베딩이란?</h3>\n<p>임베딩은 텍스트의 수치적 벡터 표현입니다. 유사한 의미를 가진 텍스트는\n유사한 벡터를 가집니다. Synapse는 각 메모리의 콘텐츠에 대해 벡터 (예:\n1536차원)를 생성합니다.</p>\n<h3>코사인 유사도</h3>\n<p>의미론적으로 유사한 메모리를 찾기 위해 Synapse는 쿼리 벡터와 각 메모리\n벡터 간의 코사인 유사도를 계산합니다. 유사도가 높을수록 더 관련성이\n높습니다.</p>\n<h2>의미론적 검색 사용 시기</h2>\n<h3>의미론적 검색을 사용할 때:</h3>\n<ul>\n<li>저장된 것과 다르게 설명된 &quot;X에 대한 메모리&quot;를 원할 때</li>\n<li>FTS5가 결과를 반환하지 않을 때 (키워드 매칭 없음)</li>\n<li>개념적 그룹화를 원할 때 (예: 일부가 &quot;release&quot;라고 말하더라도 모든 &quot;deployment&quot; 메모리)</li>\n<li>쿼리가 질문일 때: &quot;인증은 어떻게 처리합니까?&quot;</li>\n</ul>\n<h3>FTS5를 사용할 때:</h3>\n<ul>\n<li>정확한 키워드를 알 때</li>\n<li>불린 로직 (AND, OR, NOT)이 필요할 때</li>\n<li>서브밀리초 응답이 필요할 때</li>\n<li>구문 매칭을 원할 때</li>\n</ul>\n<h2>엔드포인트</h2>\n<h3>GET /memory/semantic-search</h3>\n<pre><code class=\"hljs language-bash\">curl -H <span class=\"hljs-string\">&quot;Authorization: Bearer YOUR_MIND_KEY&quot;</span> \\\n     <span class=\"hljs-string\">&quot;https://synapse.schaefer.zone/memory/semantic-search?q=container+orchestration&quot;</span></code></pre><p>응답:</p>\n<pre><code class=\"hljs language-json\"><span class=\"hljs-punctuation\">{</span>\n  <span class=\"hljs-attr\">&quot;results&quot;</span><span class=\"hljs-punctuation\">:</span> <span class=\"hljs-punctuation\">[</span>\n    <span class=\"hljs-punctuation\">{</span>\n      <span class=\"hljs-attr\">&quot;id&quot;</span><span class=\"hljs-punctuation\">:</span> <span class=\"hljs-string\">&quot;mem_001&quot;</span><span class=\"hljs-punctuation\">,</span>\n      <span class=\"hljs-attr\">&quot;category&quot;</span><span class=\"hljs-punctuation\">:</span> <span class=\"hljs-string\">&quot;project&quot;</span><span class=\"hljs-punctuation\">,</span>\n      <span class=\"hljs-attr\">&quot;key&quot;</span><span class=\"hljs-punctuation\">:</span> <span class=\"hljs-string\">&quot;project_synapse_deployment&quot;</span><span class=\"hljs-punctuation\">,</span>\n      <span class=\"hljs-attr\">&quot;content&quot;</span><span class=\"hljs-punctuation\">:</span> <span class=\"hljs-string\">&quot;Synapse deployed using Docker Swarm on vps1...&quot;</span><span class=\"hljs-punctuation\">,</span>\n      <span class=\"hljs-attr\">&quot;tags&quot;</span><span class=\"hljs-punctuation\">:</span> <span class=\"hljs-punctuation\">[</span><span class=\"hljs-string\">&quot;docker&quot;</span><span class=\"hljs-punctuation\">,</span> <span class=\"hljs-string\">&quot;swarm&quot;</span><span class=\"hljs-punctuation\">,</span> <span class=\"hljs-string\">&quot;deployment&quot;</span><span class=\"hljs-punctuation\">]</span><span class=\"hljs-punctuation\">,</span>\n      <span class=\"hljs-attr\">&quot;similarity&quot;</span><span class=\"hljs-punctuation\">:</span> <span class=\"hljs-number\">0.89</span>\n    <span class=\"hljs-punctuation\">}</span><span class=\"hljs-punctuation\">,</span>\n    <span class=\"hljs-punctuation\">{</span>\n      <span class=\"hljs-attr\">&quot;id&quot;</span><span class=\"hljs-punctuation\">:</span> <span class=\"hljs-string\">&quot;mem_042&quot;</span><span class=\"hljs-punctuation\">,</span>\n      <span class=\"hljs-attr\">&quot;category&quot;</span><span class=\"hljs-punctuation\">:</span> <span class=\"hljs-string\">&quot;fact&quot;</span><span class=\"hljs-punctuation\">,</span>\n      <span class=\"hljs-attr\">&quot;key&quot;</span><span class=\"hljs-punctuation\">:</span> <span class=\"hljs-string\">&quot;kubernetes_cluster&quot;</span><span class=\"hljs-punctuation\">,</span>\n      <span class=\"hljs-attr\">&quot;content&quot;</span><span class=\"hljs-punctuation\">:</span> <span class=\"hljs-string\">&quot;We use Kubernetes for production orchestration...&quot;</span><span class=\"hljs-punctuation\">,</span>\n      <span class=\"hljs-attr\">&quot;tags&quot;</span><span class=\"hljs-punctuation\">:</span> <span class=\"hljs-punctuation\">[</span><span class=\"hljs-string\">&quot;kubernetes&quot;</span><span class=\"hljs-punctuation\">,</span> <span class=\"hljs-string\">&quot;orchestration&quot;</span><span class=\"hljs-punctuation\">]</span><span class=\"hljs-punctuation\">,</span>\n      <span class=\"hljs-attr\">&quot;similarity&quot;</span><span class=\"hljs-punctuation\">:</span> <span class=\"hljs-number\">0.84</span>\n    <span class=\"hljs-punctuation\">}</span>\n  <span class=\"hljs-punctuation\">]</span>\n<span class=\"hljs-punctuation\">}</span></code></pre><h2>예시</h2>\n<h3>배포 메모리 찾기</h3>\n<pre><code class=\"hljs language-bash\"><span class=\"hljs-comment\"># FTS5 might miss some — semantic catches all</span>\ncurl .../memory/semantic-search?q=deployment+process</code></pre><p>&quot;deployment&quot;, &quot;release&quot;, &quot;publishing&quot;, &quot;rolling out&quot; 등에 대한 메모리를\n반환합니다.</p>\n<h3>인증 패턴 찾기</h3>\n<pre><code class=\"hljs language-bash\">curl .../memory/semantic-search?q=how+<span class=\"hljs-keyword\">do</span>+<span class=\"hljs-built_in\">users</span>+<span class=\"hljs-built_in\">log</span>+<span class=\"hljs-keyword\">in</span></code></pre><p>login, auth, JWT, session management, OAuth 등에 대한 메모리를 반환합니다.</p>\n<h3>유사한 메모리 찾기</h3>\n<pre><code class=\"hljs language-bash\"><span class=\"hljs-comment\"># Find memories similar to a specific one</span>\ncurl .../memory/related/mem_001</code></pre><p>(공유 태그 및 임베딩 벡터를 통해) 의미론적 유사도를 사용합니다.</p>\n<h2>임베딩 생성</h2>\n<h3>임베딩은 언제 생성되나요?</h3>\n<ul>\n<li><strong>메모리 저장 시</strong> — 임베딩 서비스가 구성된 경우, 동기적으로 임베딩 생성</li>\n<li><strong>배치 생성</strong> — <code>POST /memory/embed-batch</code>가 임베딩이 없는 메모리의 임베딩 생성</li>\n<li><strong>비동기 업데이트</strong> — 콘텐츠가 업데이트되면 임베딩 재생성</li>\n</ul>\n<h3>임베딩 제공자</h3>\n<p>Synapse는 구성 가능한 임베딩 제공자를 지원합니다:</p>\n<ul>\n<li><strong>OpenAI</strong> (<code>text-embedding-3-small</code>, <code>text-embedding-3-large</code>)</li>\n<li><strong>로컬 모델</strong> (Ollama 등을 통해)</li>\n<li><strong>사용자 정의</strong> (임베딩 인터페이스 구현)</li>\n</ul>\n<p>환경 변수로 구성:</p>\n<pre><code class=\"hljs language-bash\">EMBEDDINGS_PROVIDER=openai\nEMBEDDINGS_API_KEY=sk-...\nEMBEDDINGS_MODEL=text-embedding-3-small</code></pre><h3>배치 생성</h3>\n<p>임베딩이 누락된 메모리가 많은 마인드의 경우:</p>\n<pre><code class=\"hljs language-bash\"><span class=\"hljs-comment\"># Generate embeddings for up to 100 memories</span>\ncurl -X POST https://synapse.schaefer.zone/memory/embed-batch \\\n  -H <span class=\"hljs-string\">&quot;Authorization: Bearer YOUR_MIND_KEY&quot;</span> \\\n  -H <span class=\"hljs-string\">&quot;Content-Type: application/json&quot;</span> \\\n  -d <span class=\"hljs-string\">&#x27;{&quot;limit&quot;: 100}&#x27;</span>\n\n<span class=\"hljs-comment\"># Check progress</span>\ncurl -H <span class=\"hljs-string\">&quot;Authorization: Bearer YOUR_MIND_KEY&quot;</span> \\\n     https://synapse.schaefer.zone/memory/embed-batch-status</code></pre><h2>성능</h2>\n<table>\n<thead>\n<tr>\n<th>작업</th>\n<th>지연 시간</th>\n</tr>\n</thead>\n<tbody><tr>\n<td>임베딩 생성 (OpenAI)</td>\n<td>100-200ms</td>\n</tr>\n<tr>\n<td>의미론적 검색 (1k 메모리)</td>\n<td>50-100ms</td>\n</tr>\n<tr>\n<td>의미론적 검색 (10k 메모리)</td>\n<td>200-500ms</td>\n</tr>\n<tr>\n<td>배치 생성 (100 메모리)</td>\n<td>10-20s</td>\n</tr>\n</tbody></table>\n<div class=\"callout callout-note\">의미론적 검색은 벡터 계산으로 인해 FTS5보다 느립니다. 알려진 키워드에는\nFTS5를, 개념적 쿼리에는 의미론적 검색을 사용하십시오.</div><h2>제한 사항</h2>\n<h3>임베딩 비용</h3>\n<p>OpenAI를 사용하는 경우, 임베딩 생성에 비용이 듭니다 (text-embedding-3-small의\n경우 1M 토큰당 ~$0.02). 평균 100 토큰인 10,000개 메모리의 경우\n~$0.02 — 무시할 수 있는 수준입니다.</p>\n<h3>콜드 스타트</h3>\n<p>임베딩이 구성되기 전에 저장된 메모리는 임베딩이 없습니다. <code>POST /memory/embed-batch</code>를 실행하여 백필하십시오.</p>\n<h3>제공자 의존성</h3>\n<p>임베딩 제공자가 다운된 경우, 의미론적 검색은 정상적으로 실패합니다 (빈\n결과 또는 오류 반환). FTS5는 여전히 작동합니다.</p>\n<h2>임베딩을 사용할 수 없는 경우</h2>\n<p>임베딩 서비스가 구성되지 않은 경우:</p>\n<ul>\n<li><code>GET /memory/semantic-search</code>가 503 Service Unavailable 반환</li>\n<li><code>POST /memory</code>는 여전히 작동 (임베딩만 생성 안 됨)</li>\n<li>FTS5 검색은 여전히 작동</li>\n</ul>\n<h2>모범 사례</h2>\n<div class=\"callout callout-ok\"></div><h2>다음 단계</h2>\n<ul>\n<li><a href=\"/docs/concepts/fts5-search\">FTS5 검색</a></li>\n<li><a href=\"/docs/api/memory\">Memory API</a></li>\n<li><a href=\"/docs/concepts/architecture\">아키텍처</a></li>\n</ul>\n","urls":{"html":"/docs/concepts/semantic-search","text":"/docs/concepts/semantic-search?format=text","json":"/docs/concepts/semantic-search?format=json","llm":"/docs/concepts/semantic-search?format=llm"},"translations_available":["en","zh","hi","es","fr","ar","pt","ru","ja","de","it","ko","nl","pl","tr","sv","vi","th","id","uk"]}