<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ko">
	<id>https://s3wiki.yonsei.ac.kr/index.php?action=history&amp;feed=atom&amp;title=%EB%8F%84%EC%9B%80%EB%A7%90%3AS3_%EC%97%B0%EA%B5%AC_%EB%A9%94%EB%AA%A8%EB%A6%AC%2F%EB%B2%A1%ED%84%B0%C2%B7%ED%95%98%EC%9D%B4%EB%B8%8C%EB%A6%AC%EB%93%9C_%EA%B2%80%EC%83%89_%EC%84%A4%EA%B3%84</id>
	<title>도움말:S3 연구 메모리/벡터·하이브리드 검색 설계 - 편집 역사</title>
	<link rel="self" type="application/atom+xml" href="https://s3wiki.yonsei.ac.kr/index.php?action=history&amp;feed=atom&amp;title=%EB%8F%84%EC%9B%80%EB%A7%90%3AS3_%EC%97%B0%EA%B5%AC_%EB%A9%94%EB%AA%A8%EB%A6%AC%2F%EB%B2%A1%ED%84%B0%C2%B7%ED%95%98%EC%9D%B4%EB%B8%8C%EB%A6%AC%EB%93%9C_%EA%B2%80%EC%83%89_%EC%84%A4%EA%B3%84"/>
	<link rel="alternate" type="text/html" href="https://s3wiki.yonsei.ac.kr/index.php?title=%EB%8F%84%EC%9B%80%EB%A7%90:S3_%EC%97%B0%EA%B5%AC_%EB%A9%94%EB%AA%A8%EB%A6%AC/%EB%B2%A1%ED%84%B0%C2%B7%ED%95%98%EC%9D%B4%EB%B8%8C%EB%A6%AC%EB%93%9C_%EA%B2%80%EC%83%89_%EC%84%A4%EA%B3%84&amp;action=history"/>
	<updated>2026-09-08T08:36:47Z</updated>
	<subtitle>이 문서의 편집 역사</subtitle>
	<generator>MediaWiki 1.43.9</generator>
	<entry>
		<id>https://s3wiki.yonsei.ac.kr/index.php?title=%EB%8F%84%EC%9B%80%EB%A7%90:S3_%EC%97%B0%EA%B5%AC_%EB%A9%94%EB%AA%A8%EB%A6%AC/%EB%B2%A1%ED%84%B0%C2%B7%ED%95%98%EC%9D%B4%EB%B8%8C%EB%A6%AC%EB%93%9C_%EA%B2%80%EC%83%89_%EC%84%A4%EA%B3%84&amp;diff=2774&amp;oldid=prev</id>
		<title>S3Admin: S3 연구 메모리 저장소 문서 동기화</title>
		<link rel="alternate" type="text/html" href="https://s3wiki.yonsei.ac.kr/index.php?title=%EB%8F%84%EC%9B%80%EB%A7%90:S3_%EC%97%B0%EA%B5%AC_%EB%A9%94%EB%AA%A8%EB%A6%AC/%EB%B2%A1%ED%84%B0%C2%B7%ED%95%98%EC%9D%B4%EB%B8%8C%EB%A6%AC%EB%93%9C_%EA%B2%80%EC%83%89_%EC%84%A4%EA%B3%84&amp;diff=2774&amp;oldid=prev"/>
		<updated>2026-07-20T05:08:47Z</updated>

		<summary type="html">&lt;p&gt;S3 연구 메모리 저장소 문서 동기화&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;ko&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← 이전 판&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;2026년 7월 20일 (월) 14:08 판&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l28&quot;&gt;28번째 줄:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;28번째 줄:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* 전체 embedding이 성공했을 때만 새 snapshot을 원자적으로 교체합니다. 한 Lesson만 실패해 성공 항목을 부분 반영하는 재시도 큐는 아직 없습니다.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* 전체 embedding이 성공했을 때만 새 snapshot을 원자적으로 교체합니다. 한 Lesson만 실패해 성공 항목을 부분 반영하는 재시도 큐는 아직 없습니다.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* 프로세스마다 active generation 하나를 메모리에 둡니다. 재시작하면 MediaWiki에서 시작한 백그라운드 작업으로 다시 만듭니다.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* 프로세스마다 active generation 하나를 메모리에 둡니다. 재시작하면 MediaWiki에서 시작한 백그라운드 작업으로 다시 만듭니다.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* relation, lexical과 semantic 순위를 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;rrf_v1&lt;/del&gt;&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;로 결합합니다. &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;후보 사이의 별도 &lt;/del&gt;diversity &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;reranking은 아직 적용하지 않습니다&lt;/del&gt;.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* relation, lexical과 semantic 순위를 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;rrf_v2&lt;/ins&gt;&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;로 결합합니다. &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;같은 점수대에서는 검증된 evidence coverage를 작은 prior로 반영하고 record origin이 한 종류로 몰리지 않도록 bounded &lt;/ins&gt;diversity &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;보정을 적용합니다&lt;/ins&gt;.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* 기존 v1 cursor envelope를 유지하고 mode, ranking version과 generation을 fingerprint에 포함합니다.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* 기존 v1 cursor envelope를 유지하고 mode, ranking version과 generation을 fingerprint에 포함합니다.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;recent changes checkpoint, tombstone, 항목별 재시도, active/rollback generation, cursor v2와 sidecar는 아래에 설명한 확장 단계에서 추가합니다.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;recent changes checkpoint, tombstone, 항목별 재시도, active/rollback generation, cursor v2와 sidecar는 아래에 설명한 확장 단계에서 추가합니다.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l49&quot;&gt;49번째 줄:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;49번째 줄:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* 검색 결과를 근거 없이 요약하거나 해결책으로 확정&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* 검색 결과를 근거 없이 요약하거나 해결책으로 확정&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* 다중 테넌트 저장소와 사용자별 비공개 인덱스&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* 다중 테넌트 저장소와 사용자별 비공개 인덱스&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;검색 scope는 별도 Lesson이나 데이터베이스가 아닙니다. 서버 설정의 이름 있는 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;SearchFilters&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; 묶음이며 호출자의 필터와 교집합으로 적용됩니다. 현재 scope는 relevance 범위만 정하고 접근 제어를 대신하지 않습니다.&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;=== 전체 구조 ===&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;=== 전체 구조 ===&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l590&quot;&gt;590번째 줄:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;592번째 줄:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* 근거와 적용 조건이 부족한 후보 비율&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* 근거와 적용 조건이 부족한 후보 비율&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* p50, p95 지연 시간과 fallback 비율&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* p50, p95 지연 시간과 fallback 비율&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;저장소의 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;scripts/evaluate-retrieval.py&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;는 중앙 MCP의 read-only &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;search_lessons&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;만 호출하고 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;recall&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;mean reciprocal rank&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;nDCG&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;, p50/p95 latency, fallback 수와 partial 응답 수를 bounded JSON으로 출력합니다. 평가 파일에는 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;query&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;expected_ids&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;, 선택적인 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;retrieval_mode&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;scope&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;를 넣고 query 본문은 결과나 로그에 쓰지 않습니다.&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;평가용 query 원문에 비밀이나 개인 정보를 넣지 않습니다. 실제 사용 기록을 저장소에 그대로 커밋하지 않습니다. 새 generation은 품질 기준, 출력 제한과 장애 fallback 테스트를 모두 통과한 뒤 활성화합니다.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;평가용 query 원문에 비밀이나 개인 정보를 넣지 않습니다. 실제 사용 기록을 저장소에 그대로 커밋하지 않습니다. 새 generation은 품질 기준, 출력 제한과 장애 fallback 테스트를 모두 통과한 뒤 활성화합니다.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l600&quot;&gt;600번째 줄:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;604번째 줄:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;# &amp;#039;&amp;#039;&amp;#039;완료:&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;find_analogies&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;와 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;search_lessons&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;에 명시적 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;hybrid_v1&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; mode를 적용했습니다. 기본 mode는 바꾸지 않았습니다.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;# &amp;#039;&amp;#039;&amp;#039;완료:&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;find_analogies&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;와 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;search_lessons&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;에 명시적 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;hybrid_v1&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; mode를 적용했습니다. 기본 mode는 바꾸지 않았습니다.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;# &amp;#039;&amp;#039;&amp;#039;완료:&amp;#039;&amp;#039;&amp;#039; revision ID를 포함한 조회, 조건부 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;revise_lesson&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;, bounded &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;audit_lessons&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;와 full citation 조회를 추가했습니다. 이 도구들은 기준 MediaWiki를 읽고 쓰며 별도 검색 저장소를 만들지 않습니다.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;# &amp;#039;&amp;#039;&amp;#039;완료:&amp;#039;&amp;#039;&amp;#039; revision ID를 포함한 조회, 조건부 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;revise_lesson&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;, bounded &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;audit_lessons&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;와 full citation 조회를 추가했습니다. 이 도구들은 기준 MediaWiki를 읽고 쓰며 별도 검색 저장소를 만들지 않습니다.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;# &#039;&#039;&#039;완료:&#039;&#039;&#039; 서버 설정 scope와 고정 평가셋 기반 read-only 품질 측정을 추가했습니다.&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;# &#039;&#039;&#039;완료:&#039;&#039;&#039; code/docs 파일과 Slack export를 Lesson 이전의 bounded 후보로 읽는 connector를 추가했습니다. connector는 비밀값을 마스킹하고 중앙 저장소에 쓰지 않습니다.&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;# &#039;&#039;&#039;완료:&#039;&#039;&#039; 세 facet 병렬 planner, bounded RRF executor, 선택적 OpenAI-compatible reranker와 인용 제한 synthesis CLI를 추가했습니다.&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;# &#039;&#039;&#039;완료:&#039;&#039;&#039; scope별 optional principal allowlist를 추가했습니다. 이는 relevance scope 사용 권한만 보호하며 Lesson 필드나 canonical 저장 정책을 바꾸지 않습니다.&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;# &amp;#039;&amp;#039;&amp;#039;운영 후속:&amp;#039;&amp;#039;&amp;#039; 고정 평가셋과 shadow 측정으로 품질, 비용, p95, fallback 비율을 확인한 뒤 활성화 범위를 정합니다.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;# &amp;#039;&amp;#039;&amp;#039;운영 후속:&amp;#039;&amp;#039;&amp;#039; 고정 평가셋과 shadow 측정으로 품질, 비용, p95, fallback 비율을 확인한 뒤 활성화 범위를 정합니다.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;# &amp;#039;&amp;#039;&amp;#039;확장 후속:&amp;#039;&amp;#039;&amp;#039; recent changes checkpoint, tombstone과 지속형 generation을 추가합니다.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;# &amp;#039;&amp;#039;&amp;#039;확장 후속:&amp;#039;&amp;#039;&amp;#039; recent changes checkpoint, tombstone과 지속형 generation을 추가합니다.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;# &amp;#039;&amp;#039;&amp;#039;조건부 후속:&amp;#039;&amp;#039;&amp;#039; 실제 지표가 전환 기준을 넘을 때만 sidecar 또는 공유 검색 서비스로 옮깁니다.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;# &amp;#039;&amp;#039;&amp;#039;조건부 후속:&amp;#039;&amp;#039;&amp;#039; 실제 지표가 전환 기준을 넘을 때만 sidecar 또는 공유 검색 서비스로 옮깁니다.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;각 단계에서 기존 최대 20건, cursor, &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;partial&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;scanned&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;scan_limit&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;와 UTF-8 직렬화 상한을 유지합니다. 모델, 응답 또는 검색 정책이 바뀌면 MCP 모델, 예시와 문서를 함께 수정합니다.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;각 단계에서 기존 최대 20건, cursor, &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;partial&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;scanned&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;scan_limit&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;와 UTF-8 직렬화 상한을 유지합니다. 모델, 응답 또는 검색 정책이 바뀌면 MCP 모델, 예시와 문서를 함께 수정합니다.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;

&lt;!-- diff cache key s3_research_memory:diff:1.41:old-1728:rev-2774:php=table --&gt;
&lt;/table&gt;</summary>
		<author><name>S3Admin</name></author>
	</entry>
	<entry>
		<id>https://s3wiki.yonsei.ac.kr/index.php?title=%EB%8F%84%EC%9B%80%EB%A7%90:S3_%EC%97%B0%EA%B5%AC_%EB%A9%94%EB%AA%A8%EB%A6%AC/%EB%B2%A1%ED%84%B0%C2%B7%ED%95%98%EC%9D%B4%EB%B8%8C%EB%A6%AC%EB%93%9C_%EA%B2%80%EC%83%89_%EC%84%A4%EA%B3%84&amp;diff=1728&amp;oldid=prev</id>
		<title>S3Admin: S3 연구 메모리 저장소 문서 동기화</title>
		<link rel="alternate" type="text/html" href="https://s3wiki.yonsei.ac.kr/index.php?title=%EB%8F%84%EC%9B%80%EB%A7%90:S3_%EC%97%B0%EA%B5%AC_%EB%A9%94%EB%AA%A8%EB%A6%AC/%EB%B2%A1%ED%84%B0%C2%B7%ED%95%98%EC%9D%B4%EB%B8%8C%EB%A6%AC%EB%93%9C_%EA%B2%80%EC%83%89_%EC%84%A4%EA%B3%84&amp;diff=1728&amp;oldid=prev"/>
		<updated>2026-07-18T10:09:47Z</updated>

		<summary type="html">&lt;p&gt;S3 연구 메모리 저장소 문서 동기화&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;ko&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← 이전 판&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;2026년 7월 18일 (토) 19:09 판&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l13&quot;&gt;13번째 줄:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;13번째 줄:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* 벡터 인덱스는 후보 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;Lesson:&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; ID만 반환하는 파생 데이터로 둡니다.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* 벡터 인덱스는 후보 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;Lesson:&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; ID만 반환하는 파생 데이터로 둡니다.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* 최종 결과는 항상 MediaWiki 최신 리비전을 다시 읽어 만듭니다.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* 최종 결과는 항상 MediaWiki 최신 리비전을 다시 읽어 만듭니다.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* 외부 MCP 도구 &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;아홉 &lt;/del&gt;개와 중앙 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;/mcp&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; 진입점은 그대로 유지합니다.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* 외부 MCP 도구 &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;열 &lt;/ins&gt;개와 중앙 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;/mcp&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; 진입점은 그대로 유지합니다.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* 전체 텍스트, 의미 유사도, 명시적 relation을 각각 찾은 뒤 결정적인 규칙으로 합칩니다.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* 전체 텍스트, 의미 유사도, 명시적 relation을 각각 찾은 뒤 결정적인 규칙으로 합칩니다.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* 1단계에서는 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;mcp-http&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; 프로세스 안에서 exact vector search를 사용합니다.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* 1단계에서는 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;mcp-http&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; 프로세스 안에서 exact vector search를 사용합니다.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l292&quot;&gt;292번째 줄:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;292번째 줄:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;|}&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;|}&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;title&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;은 전체 텍스트 검색에서 높은 가중치로 다룹니다. evidence 개요, 구조화된 인용, note, URL, &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;verification_basis&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;, author, reviewer, timestamp와 relation은 임베딩하지 않습니다. 이 값은 검색 근거, 필터, 감사 또는 relation 후보 경로에서 따로 사용합니다. &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;metadata_only&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; evidence가 있다는 이유만으로 Lesson 전체를 제외하지 않습니다. 한 Lesson에 서로 다른 확인 범위의 근거가 함께 있을 수 있기 때문입니다.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;title&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;은 전체 텍스트 검색에서 높은 가중치로 다룹니다. evidence 개요, 구조화된 인용, note, URL, &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;verification_basis&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;, append-only evidence 검증 기록&lt;/ins&gt;, author, reviewer, timestamp와 relation은 임베딩하지 않습니다. 이 값은 검색 근거, 필터, 감사 또는 relation 후보 경로에서 따로 사용합니다. &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;metadata_only&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; evidence가 있다는 이유만으로 Lesson 전체를 제외하지 않습니다. 한 Lesson에 서로 다른 확인 범위의 근거가 함께 있을 수 있기 때문입니다.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;입력은 다음 규칙으로 만듭니다.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;입력은 다음 규칙으로 만듭니다.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;

&lt;!-- diff cache key s3_research_memory:diff:1.41:old-1187:rev-1728:php=table --&gt;
&lt;/table&gt;</summary>
		<author><name>S3Admin</name></author>
	</entry>
	<entry>
		<id>https://s3wiki.yonsei.ac.kr/index.php?title=%EB%8F%84%EC%9B%80%EB%A7%90:S3_%EC%97%B0%EA%B5%AC_%EB%A9%94%EB%AA%A8%EB%A6%AC/%EB%B2%A1%ED%84%B0%C2%B7%ED%95%98%EC%9D%B4%EB%B8%8C%EB%A6%AC%EB%93%9C_%EA%B2%80%EC%83%89_%EC%84%A4%EA%B3%84&amp;diff=1187&amp;oldid=prev</id>
		<title>S3Admin: S3 연구 메모리 저장소 문서 동기화</title>
		<link rel="alternate" type="text/html" href="https://s3wiki.yonsei.ac.kr/index.php?title=%EB%8F%84%EC%9B%80%EB%A7%90:S3_%EC%97%B0%EA%B5%AC_%EB%A9%94%EB%AA%A8%EB%A6%AC/%EB%B2%A1%ED%84%B0%C2%B7%ED%95%98%EC%9D%B4%EB%B8%8C%EB%A6%AC%EB%93%9C_%EA%B2%80%EC%83%89_%EC%84%A4%EA%B3%84&amp;diff=1187&amp;oldid=prev"/>
		<updated>2026-07-18T04:04:32Z</updated>

		<summary type="html">&lt;p&gt;S3 연구 메모리 저장소 문서 동기화&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;ko&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← 이전 판&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;2026년 7월 18일 (토) 13:04 판&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l4&quot;&gt;4번째 줄:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;4번째 줄:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;=== 문서 상태 ===&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;=== 문서 상태 ===&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;이 문서는 구현된 1단계 검색 계층과 이후 확장 경계를 함께 설명합니다. 현재 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;mcp-http&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;에는 교체 가능한 임베딩 제공자, 세 가지 facet projection, copy-on-write exact vector index와 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;legacy&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;·&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;hybrid_v1&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; mode가 들어 있습니다. 기본 mode와 기본 provider는 계속 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;legacy&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;disabled&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;입니다.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;이 문서는 구현된 1단계 검색 계층과 이후 확장 경계를 함께 설명합니다. 현재 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;mcp-http&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;에는 교체 가능한 임베딩 제공자, 세 가지 facet projection, copy-on-write exact vector index와 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;legacy&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;·&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;hybrid_v1&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; mode가 들어 있습니다. 기본 mode와 기본 provider는 계속 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;legacy&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;disabled&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;입니다&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;. 선택적 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;embedding&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; Compose profile에는 이 서버의 Vega GPU에서 확인한 Qwen3 F16 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;llama.cpp&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; Vulkan 서비스와 검증 downloader가 들어 있습니다&lt;/ins&gt;.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;recent changes poll, 지속형 checkpoint·tombstone, 별도 sidecar, 여러 MCP 인스턴스가 공유하는 generation, cursor v2와 자동 품질 cutover는 아직 후속 단계입니다. 아래 설계에서 이 항목은 구현 목표로 읽습니다.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;recent changes poll, 지속형 checkpoint·tombstone, 별도 sidecar, 여러 MCP 인스턴스가 공유하는 generation, cursor v2와 자동 품질 cutover는 아직 후속 단계입니다. 아래 설계에서 이 항목은 구현 목표로 읽습니다.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l242&quot;&gt;242번째 줄:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;242번째 줄:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* 한 입력의 최대 token 수&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* 한 입력의 최대 token 수&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;외부 API, 서버 안의 모델 또는 별도 내부 추론 서비스는 같은 인터페이스를 구현할 수 있습니다.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;외부 API, 서버 안의 모델 또는 별도 내부 추론 서비스는 같은 인터페이스를 구현할 수 있습니다.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;현재 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;s3rm-qwen3-retrieval-v1&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; profile은 다음을 하나의 generation 입력으로 묶습니다.&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;* &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;Qwen/Qwen3-Embedding-0.6B&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; artifact SHA-256과 1024차원&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;* last pooling과 16K token 입력 계약&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;* 희귀 CJK byte fallback을 포함해 16K 안에 두는 document facet 4,000자 상한&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;* &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;situation&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;approach&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;mechanism&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;별 영문 query instruction&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;* instruction을 붙이지 않는 document 형식&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;* provider의 입력 개수·문자 수 상한&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;HTTP endpoint와 인증은 transport 설정이며 profile의 의미 계약과 분리합니다. 모델 파일, pooling, instruction 또는 차원을 바꾸면 profile generation이 달라져 전체 exact index를 새로 만듭니다. 서로 다른 벡터 공간은 섞지 않습니다. 외부 provider로 자동 failover하지 않으며 사용할 snapshot이 없으면 legacy 검색으로 대체합니다.&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;==== 색인 동기화 ====&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;==== 색인 동기화 ====&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l475&quot;&gt;475번째 줄:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;485번째 줄:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;|}&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;|}&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;MCP 쓰기는 항상 MediaWiki에 먼저 저장합니다. 1단계에서는 Lesson 생성이나 핵심 내용 revision 성공 뒤 프로세스 안의 dirty hint를 남기고 단일 백그라운드 refresh를 시작합니다. evidence와 relation만 추가하면 현재 projection 본문은 바뀌지 않으므로 재임베딩하지 않습니다. 브라우저 편집은 최소 대조 간격이 지난 hybrid 요청이 백그라운드 refresh를 시작할 때 발견합니다. hybrid 요청 자체는 전체 대조를 기다리지 않습니다. 사용할 snapshot이 있으면 갱신 중에도 그 세대를 사용하고 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;stale&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; 상태를 표시하며, 없으면 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;building&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;으로 즉시 legacy 검색을 반환합니다. hint나 임베딩이 실패해도 위키 쓰기는 되돌리지 않습니다.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;MCP 쓰기는 항상 MediaWiki에 먼저 저장합니다. 1단계에서는 Lesson 생성이나 핵심 내용 revision 성공 뒤 프로세스 안의 dirty hint를 남기고 단일 백그라운드 refresh를 시작합니다. evidence와 relation만 추가하면 현재 projection 본문은 바뀌지 않으므로 재임베딩하지 않습니다. 브라우저 편집은 최소 대조 간격이 지난 hybrid 요청이 백그라운드 refresh를 시작할 때 발견합니다&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;. 대조 결과 Lesson 수와 모든 projection hash가 같으면 모델을 다시 호출하지 않습니다&lt;/ins&gt;. hybrid 요청 자체는 전체 대조를 기다리지 않습니다. 사용할 snapshot이 있으면 갱신 중에도 그 세대를 사용하고 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;stale&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; 상태를 표시하며, 없으면 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;building&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;으로 즉시 legacy 검색을 반환합니다. hint나 임베딩이 실패해도 위키 쓰기는 되돌리지 않습니다.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;1단계 refresh는 all-or-nothing입니다. 한 Lesson이라도 임베딩하지 못하면 기존 snapshot을 유지하고 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;degraded&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;, 기존 snapshot이 없으면 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;unavailable&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;로 표시합니다. 항목별 재시도 큐와 recent changes poll은 후속 동기화 단계에서 추가합니다.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;1단계 refresh는 all-or-nothing입니다. 한 Lesson이라도 임베딩하지 못하면 기존 snapshot을 유지하고 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;degraded&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;, 기존 snapshot이 없으면 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;unavailable&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;로 표시합니다. 항목별 재시도 큐와 recent changes poll은 후속 동기화 단계에서 추가합니다.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;

&lt;!-- diff cache key s3_research_memory:diff:1.41:old-1163:rev-1187:php=table --&gt;
&lt;/table&gt;</summary>
		<author><name>S3Admin</name></author>
	</entry>
	<entry>
		<id>https://s3wiki.yonsei.ac.kr/index.php?title=%EB%8F%84%EC%9B%80%EB%A7%90:S3_%EC%97%B0%EA%B5%AC_%EB%A9%94%EB%AA%A8%EB%A6%AC/%EB%B2%A1%ED%84%B0%C2%B7%ED%95%98%EC%9D%B4%EB%B8%8C%EB%A6%AC%EB%93%9C_%EA%B2%80%EC%83%89_%EC%84%A4%EA%B3%84&amp;diff=1163&amp;oldid=prev</id>
		<title>S3Admin: S3 연구 메모리 저장소 문서 동기화</title>
		<link rel="alternate" type="text/html" href="https://s3wiki.yonsei.ac.kr/index.php?title=%EB%8F%84%EC%9B%80%EB%A7%90:S3_%EC%97%B0%EA%B5%AC_%EB%A9%94%EB%AA%A8%EB%A6%AC/%EB%B2%A1%ED%84%B0%C2%B7%ED%95%98%EC%9D%B4%EB%B8%8C%EB%A6%AC%EB%93%9C_%EA%B2%80%EC%83%89_%EC%84%A4%EA%B3%84&amp;diff=1163&amp;oldid=prev"/>
		<updated>2026-07-18T03:14:11Z</updated>

		<summary type="html">&lt;p&gt;S3 연구 메모리 저장소 문서 동기화&lt;/p&gt;
&lt;a href=&quot;https://s3wiki.yonsei.ac.kr/index.php?title=%EB%8F%84%EC%9B%80%EB%A7%90:S3_%EC%97%B0%EA%B5%AC_%EB%A9%94%EB%AA%A8%EB%A6%AC/%EB%B2%A1%ED%84%B0%C2%B7%ED%95%98%EC%9D%B4%EB%B8%8C%EB%A6%AC%EB%93%9C_%EA%B2%80%EC%83%89_%EC%84%A4%EA%B3%84&amp;amp;diff=1163&amp;amp;oldid=202&quot;&gt;차이 보기&lt;/a&gt;</summary>
		<author><name>S3Admin</name></author>
	</entry>
	<entry>
		<id>https://s3wiki.yonsei.ac.kr/index.php?title=%EB%8F%84%EC%9B%80%EB%A7%90:S3_%EC%97%B0%EA%B5%AC_%EB%A9%94%EB%AA%A8%EB%A6%AC/%EB%B2%A1%ED%84%B0%C2%B7%ED%95%98%EC%9D%B4%EB%B8%8C%EB%A6%AC%EB%93%9C_%EA%B2%80%EC%83%89_%EC%84%A4%EA%B3%84&amp;diff=202&amp;oldid=prev</id>
		<title>S3Admin: S3 연구 메모리 저장소 문서 게시</title>
		<link rel="alternate" type="text/html" href="https://s3wiki.yonsei.ac.kr/index.php?title=%EB%8F%84%EC%9B%80%EB%A7%90:S3_%EC%97%B0%EA%B5%AC_%EB%A9%94%EB%AA%A8%EB%A6%AC/%EB%B2%A1%ED%84%B0%C2%B7%ED%95%98%EC%9D%B4%EB%B8%8C%EB%A6%AC%EB%93%9C_%EA%B2%80%EC%83%89_%EC%84%A4%EA%B3%84&amp;diff=202&amp;oldid=prev"/>
		<updated>2026-07-16T14:32:08Z</updated>

		<summary type="html">&lt;p&gt;S3 연구 메모리 저장소 문서 게시&lt;/p&gt;
&lt;p&gt;&lt;b&gt;새 문서&lt;/b&gt;&lt;/p&gt;&lt;div&gt;&amp;lt;!-- S3RM managed repository document; edit the Markdown source, not this page. --&amp;gt;&lt;br /&gt;
&amp;#039;&amp;#039;이 페이지는 저장소 문서에서 자동으로 동기화됩니다. 위키에서 직접 편집하지 마세요.&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
=== 문서 상태 ===&lt;br /&gt;
&lt;br /&gt;
이 문서는 추후 도입할 검색 계층의 설계안입니다. 현재 서비스는 MediaWiki 전체 텍스트 검색과 제한된 단어 겹침으로 동작합니다. 이 문서에 나온 벡터 인덱스, 설정값, 응답 필드는 아직 구현된 기능이 아닙니다.&lt;br /&gt;
&lt;br /&gt;
=== 결정 요약 ===&lt;br /&gt;
&lt;br /&gt;
* Semantic MediaWiki를 유일한 기준 저장소로 유지합니다.&lt;br /&gt;
* 벡터 인덱스는 후보 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;Lesson:&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; ID만 반환하는 파생 데이터로 둡니다.&lt;br /&gt;
* 최종 결과는 항상 MediaWiki 최신 리비전을 다시 읽어 만듭니다.&lt;br /&gt;
* 외부 MCP 도구 일곱 개와 중앙 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;/mcp&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; 진입점은 그대로 유지합니다.&lt;br /&gt;
* 전체 텍스트, 의미 유사도, 명시적 relation을 각각 찾은 뒤 결정적인 규칙으로 합칩니다.&lt;br /&gt;
* 처음에는 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;mcp-http&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; 프로세스 안에서 exact vector search를 사용합니다.&lt;br /&gt;
* 재구축 시간, 메모리 또는 지연 시간이 목표를 넘을 때만 내부 검색 서비스로 옮깁니다.&lt;br /&gt;
* 임베딩 모델, 입력 구성 또는 거리 계산이 바뀌면 새 인덱스 세대를 만듭니다.&lt;br /&gt;
* 의미 검색이 실패해도 전체 텍스트와 relation 검색은 계속 제공합니다.&lt;br /&gt;
벡터 저장 제품은 이 경계를 구현하는 선택 사항입니다. 검색 품질과 운영 규모를 확인하기 전에 제품별 API가 도메인 계층으로 퍼지지 않게 합니다.&lt;br /&gt;
&lt;br /&gt;
=== 목표 ===&lt;br /&gt;
&lt;br /&gt;
다음 문제를 해결합니다.&lt;br /&gt;
&lt;br /&gt;
# 표현이 달라도 증상과 제약이 비슷한 Lesson을 찾습니다.&lt;br /&gt;
# 비슷한 문제에 쓰인 서로 다른 해결 원리를 함께 보여 줍니다.&lt;br /&gt;
# 한국어, 영어와 두 언어가 섞인 메모를 같은 검색 흐름에서 다룹니다.&lt;br /&gt;
# 새 Lesson은 기존 전체 텍스트 검색으로 바로 찾을 수 있게 합니다.&lt;br /&gt;
# 임베딩 제공자와 인덱스 구현을 중단 없이 바꿀 수 있게 합니다.&lt;br /&gt;
# 여러 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;mcp-http&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; 인스턴스로 확장해도 같은 검색 세대를 사용하게 합니다.&lt;br /&gt;
다음 기능은 이 설계의 범위에 넣지 않습니다.&lt;br /&gt;
&lt;br /&gt;
* 벡터 유사도를 사실, 인과관계 또는 relation으로 자동 저장&lt;br /&gt;
* 별도 Lesson 데이터베이스 또는 사용자별 지식 사본&lt;br /&gt;
* 벡터 저장 제품의 범용 API를 MCP 도구로 공개&lt;br /&gt;
* 검색 결과를 근거 없이 요약하거나 해결책으로 확정&lt;br /&gt;
* 다중 테넌트 저장소와 사용자별 비공개 인덱스&lt;br /&gt;
=== 전체 구조 ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
flowchart LR&lt;br /&gt;
    C[&amp;quot;MCP 클라이언트&amp;quot;] --&amp;gt; M[&amp;quot;중앙 mcp-http&amp;quot;]&lt;br /&gt;
    M --&amp;gt; R[&amp;quot;검색 조정 계층&amp;quot;]&lt;br /&gt;
    R --&amp;gt; L[&amp;quot;MediaWiki 전체 텍스트 후보&amp;quot;]&lt;br /&gt;
    R --&amp;gt; G[&amp;quot;MediaWiki relation 후보&amp;quot;]&lt;br /&gt;
    R --&amp;gt; V[&amp;quot;의미 검색 후보&amp;quot;]&lt;br /&gt;
    L --&amp;gt; F[&amp;quot;후보 결합과 다양성 정렬&amp;quot;]&lt;br /&gt;
    G --&amp;gt; F&lt;br /&gt;
    V --&amp;gt; F&lt;br /&gt;
    F --&amp;gt; H[&amp;quot;MediaWiki 최신 리비전 일괄 조회&amp;quot;]&lt;br /&gt;
    H --&amp;gt; O[&amp;quot;필터·페이지 나누기·출력 제한&amp;quot;]&lt;br /&gt;
&lt;br /&gt;
    W[&amp;quot;Semantic MediaWiki 리비전&amp;quot;] --&amp;gt; I[&amp;quot;비공개 색인기&amp;quot;]&lt;br /&gt;
    I --&amp;gt; P[&amp;quot;버전이 있는 입력 구성&amp;quot;]&lt;br /&gt;
    P --&amp;gt; E[&amp;quot;교체 가능한 임베딩 제공자&amp;quot;]&lt;br /&gt;
    E --&amp;gt; X[&amp;quot;세대별 파생 벡터 인덱스&amp;quot;]&lt;br /&gt;
    X --&amp;gt; V&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
읽기 경로와 색인 경로를 분리합니다. 검색 요청이 벡터 인덱스를 직접 읽더라도 최종 Lesson 본문과 필터 판정은 MediaWiki에서 가져옵니다. 색인 실패는 위키 쓰기를 되돌리지 않습니다.&lt;br /&gt;
&lt;br /&gt;
=== 내부 경계 ===&lt;br /&gt;
&lt;br /&gt;
현재 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;WikiAdapter&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;에는 기준 저장소 작업과 후보 검색이 함께 있습니다. 동작을 바꾸기 전에 다음 경계로 나눕니다.&lt;br /&gt;
&lt;br /&gt;
==== Lesson 저장소 ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;LessonRepository&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;는 MediaWiki 읽기와 허용된 쓰기만 담당합니다.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
@dataclass(frozen=True, slots=True)&lt;br /&gt;
class LessonSnapshot:&lt;br /&gt;
    lesson: Lesson&lt;br /&gt;
    revision_id: int&lt;br /&gt;
    retrieval_hash: str&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class LessonRepository(Protocol):&lt;br /&gt;
    async def get_snapshot(&lt;br /&gt;
        self, lesson_id: str&lt;br /&gt;
    ) -&amp;gt; LessonSnapshot | None: ...&lt;br /&gt;
&lt;br /&gt;
    async def get_snapshots(&lt;br /&gt;
        self, lesson_ids: Sequence[str]&lt;br /&gt;
    ) -&amp;gt; dict[str, LessonSnapshot]: ...&lt;br /&gt;
&lt;br /&gt;
    async def create_lesson(self, lesson: Lesson) -&amp;gt; Lesson: ...&lt;br /&gt;
    async def add_relation(&lt;br /&gt;
        self, relation: LessonRelation&lt;br /&gt;
    ) -&amp;gt; LessonRelation: ...&lt;br /&gt;
    async def add_evidence(&lt;br /&gt;
        self, lesson_id: str, evidence: Evidence&lt;br /&gt;
    ) -&amp;gt; Evidence: ...&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;get_snapshots&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;는 후보 ID를 최대 50개씩 읽습니다. &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;retrieval_hash&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;는 임베딩 대상 필드만 정규화해 만든 해시입니다. 근거나 relation만 바뀌어 리비전 ID가 달라져도 이 해시가 같으면 기존 벡터를 계속 쓸 수 있습니다.&lt;br /&gt;
&lt;br /&gt;
==== 후보 검색 ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;RetrievalBackend&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;는 Lesson 본문이 아니라 작은 후보 레코드만 반환합니다.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
@dataclass(frozen=True, slots=True)&lt;br /&gt;
class RetrievalCandidate:&lt;br /&gt;
    lesson_id: str&lt;br /&gt;
    basis: str&lt;br /&gt;
    rank: int&lt;br /&gt;
    source_score: float | None&lt;br /&gt;
    indexed_revision_id: int | None&lt;br /&gt;
    indexed_retrieval_hash: str | None&lt;br /&gt;
    matched_facets: tuple[str, ...]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
@dataclass(frozen=True, slots=True)&lt;br /&gt;
class RetrievalBatch:&lt;br /&gt;
    candidates: tuple[RetrievalCandidate, ...]&lt;br /&gt;
    generation: str&lt;br /&gt;
    has_more: bool&lt;br /&gt;
    partial: bool&lt;br /&gt;
    scanned: int&lt;br /&gt;
    scan_limit: int&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class RetrievalBackend(Protocol):&lt;br /&gt;
    async def retrieve(&lt;br /&gt;
        self, request: RetrievalRequest&lt;br /&gt;
    ) -&amp;gt; RetrievalBatch: ...&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
제품별 client, collection 이름과 거리 계산 방식은 이 구현 안에 둡니다. 서비스 계층은 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;rank&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;를 기준으로 후보 경로를 합치며 raw cosine 값을 서로 직접 비교하지 않습니다. &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;source_score&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;는 한 후보 경로 안의 진단과 기준값 적용에만 씁니다. 결합이 끝난 뒤 검색 조정 계층이 별도의 서비스 점수를 만듭니다.&lt;br /&gt;
&lt;br /&gt;
==== 입력 구성과 임베딩 ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;ProjectionBuilder&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;는 같은 Lesson에서 검색 목적별 텍스트를 결정적으로 만듭니다. &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;EmbeddingProvider&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;는 텍스트 묶음을 벡터로 바꿉니다. 두 경계에는 각각 독립된 버전을 둡니다.&lt;br /&gt;
&lt;br /&gt;
임베딩 제공자는 다음 정보를 고정해 보고해야 합니다.&lt;br /&gt;
&lt;br /&gt;
* 모델 식별자와 artifact digest&lt;br /&gt;
* tokenizer 식별자와 digest&lt;br /&gt;
* 벡터 차원&lt;br /&gt;
* 정규화 여부&lt;br /&gt;
* 거리 계산 방식&lt;br /&gt;
* 한 입력의 최대 token 수&lt;br /&gt;
외부 API, 서버 안의 모델 또는 별도 내부 추론 서비스는 같은 인터페이스를 구현할 수 있습니다.&lt;br /&gt;
&lt;br /&gt;
==== 색인 동기화 ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;IndexSynchronizer&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;는 MediaWiki 변경을 읽어 파생 인덱스를 갱신합니다. MCP에는 색인 관리 도구를 추가하지 않습니다.&lt;br /&gt;
&lt;br /&gt;
* MCP 쓰기 성공 뒤 해당 Lesson을 갱신하라는 힌트를 보냅니다.&lt;br /&gt;
* 브라우저 편집을 찾기 위해 MediaWiki recent changes를 주기적으로 읽습니다.&lt;br /&gt;
* 누락된 이벤트를 복구하기 위해 전체 Lesson을 주기적으로 대조합니다.&lt;br /&gt;
* 체크포인트, 재시도 큐와 인덱스 세대는 파생 운영 상태로 취급합니다.&lt;br /&gt;
* 모든 upsert는 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;lesson_id + revision_id&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; 기준으로 반복 실행해도 같은 결과가 나와야 합니다.&lt;br /&gt;
==== 호환 이행 ====&lt;br /&gt;
&lt;br /&gt;
첫 구조 변경은 검색 결과를 바꾸지 않습니다.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;ResearchMemoryService&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;가 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;LessonRepository&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;와 선택적인 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;RetrievalBackend&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;를 받게 합니다.&lt;br /&gt;
* 검색 backend가 없으면 현재 동작을 감싼 legacy 구현을 사용합니다.&lt;br /&gt;
* 기존 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;WikiAdapter&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;의 검색 메서드는 in-memory adapter와 기존 호출자를 옮기는 동안 유지합니다.&lt;br /&gt;
* 일괄 snapshot 조회에는 단일 조회를 반복하는 기본 구현을 둘 수 있습니다.&lt;br /&gt;
* 외부 MCP 도구 이름, 입력과 응답은 이 단계에서 바꾸지 않습니다.&lt;br /&gt;
새 내부 경계와 legacy 구현의 결과가 같은지 domain-level 테스트로 확인한 뒤 의미 검색을 추가합니다.&lt;br /&gt;
&lt;br /&gt;
=== 검색용 표현 ===&lt;br /&gt;
&lt;br /&gt;
Lesson 전체를 한 벡터로 합치지 않습니다. 첫 입력 구성 버전은 세 가지 facet을 사용합니다.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! facet !! 포함하는 필드 !! 용도&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;situation&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;question&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;context&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;observation&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; || 비슷한 문제와 관찰 찾기&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;approach&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;attempt&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; || 이미 시도한 방법과 실패 형태 찾기&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;mechanism&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;interpretation&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;reusable_lesson&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;applicability&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; || 해결 원리와 적용 조건 찾기&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;title&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;은 전체 텍스트 검색에서 높은 가중치로 다룹니다. evidence 개요, 구조화된 인용, URL, author, reviewer, timestamp와 relation은 임베딩하지 않습니다. 이 값은 검색 근거, 필터 또는 relation 후보 경로에서 따로 사용합니다.&lt;br /&gt;
&lt;br /&gt;
입력은 다음 규칙으로 만듭니다.&lt;br /&gt;
&lt;br /&gt;
# Unicode NFKC로 정규화하고 연속 공백을 하나로 줄입니다.&lt;br /&gt;
# 필드 이름과 필드 값을 고정된 순서로 붙입니다.&lt;br /&gt;
# 빈 필드는 허용하지 않는 현재 Lesson 계약을 그대로 사용합니다.&lt;br /&gt;
# 모델 입력 한도를 넘으면 facet별 token 예산에 따라 앞부분과 뒷부분을 보존합니다.&lt;br /&gt;
# 잘림 여부를 색인 상태에 기록합니다.&lt;br /&gt;
# 요약용 LLM은 색인 경로에 넣지 않습니다.&lt;br /&gt;
긴 입력이 자주 잘리기 시작하면 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;ProjectionBuilder&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;만 바꿔 필드별 chunk embedding과 결정적인 pooling을 도입합니다. 이 변경도 새 입력 구성 버전과 새 인덱스 세대를 사용합니다.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;retrieval_hash&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;에는 입력 구성 버전과 정규화된 facet 텍스트를 넣습니다. 다음 값은 별도 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;metadata_hash&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;로 관리합니다.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;confidence&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;record_origin&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;author&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;review_state&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;created_at&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;updated_at&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* 구조화된 evidence 존재 여부&lt;br /&gt;
이렇게 하면 evidence 추가처럼 의미 본문이 바뀌지 않은 수정은 재임베딩하지 않고 필터 metadata만 갱신할 수 있습니다.&lt;br /&gt;
&lt;br /&gt;
=== 인덱스 레코드 ===&lt;br /&gt;
&lt;br /&gt;
파생 인덱스에는 다음 값만 저장합니다.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! 값 !! 설명&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;lesson_id&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; || MediaWiki 페이지의 고정 외부 ID&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;indexed_revision_id&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; || 색인할 때 읽은 리비전 ID&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;retrieval_hash&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; || 임베딩 대상 내용의 해시&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;metadata_hash&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; || 필터 metadata의 해시&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;updated_at&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; || 지연과 최신성 확인용 시각&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;generation&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; || 모델과 입력 구성의 세대&lt;br /&gt;
|-&lt;br /&gt;
| filter scalar || 기존 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;SearchFilters&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;를 미리 적용하기 위한 값&lt;br /&gt;
|-&lt;br /&gt;
| facet vectors || &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;situation&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;approach&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;mechanism&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; 벡터&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
정규화된 본문, evidence 전문과 relation 목록은 저장하지 않습니다. 필터 scalar는 성능 최적화용 사본입니다. 최종 결과에는 MediaWiki에서 다시 읽은 필터를 적용합니다.&lt;br /&gt;
&lt;br /&gt;
=== 후보 생성과 순위 ===&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;search_lessons&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
다음 후보 경로를 독립적으로 실행합니다.&lt;br /&gt;
&lt;br /&gt;
# MediaWiki 전체 텍스트 검색&lt;br /&gt;
# query와 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;situation&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; facet의 의미 유사도&lt;br /&gt;
# query와 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;approach&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; facet의 의미 유사도&lt;br /&gt;
# query와 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;mechanism&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; facet의 의미 유사도&lt;br /&gt;
정확한 식별자, 제목과 오류 문자열은 전체 텍스트 결과가 놓치지 않게 합니다. 의미 검색은 같은 뜻을 다른 표현으로 쓴 후보를 보완합니다.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;find_analogies&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
다음 순서로 후보를 만듭니다.&lt;br /&gt;
&lt;br /&gt;
# 저장된 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;analogous_to&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; relation 후보&lt;br /&gt;
# source의 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;situation&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;과 비슷한 후보&lt;br /&gt;
# source의 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;mechanism&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;과 비슷한 교차 문제 후보&lt;br /&gt;
# 현재 Unicode 단어와 한국어 n-gram 후보&lt;br /&gt;
relation 후보는 명시적으로 저장된 연결이라는 점을 계속 구분합니다. 벡터 후보는 relation이 아니며 자동으로 저장하지 않습니다.&lt;br /&gt;
&lt;br /&gt;
==== 결합과 다양성 ====&lt;br /&gt;
&lt;br /&gt;
백엔드마다 점수 분포가 다르므로 raw 점수를 더하지 않습니다. 각 후보 경로의 순위를 versioned reciprocal-rank fusion으로 합칩니다. 같은 해결 방식이 상위 결과를 차지하지 않도록 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;approach&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;와 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;mechanism&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; 벡터에 작은 다양성 가중치를 적용합니다.&lt;br /&gt;
&lt;br /&gt;
다양성은 관련성을 대체하지 않습니다. 먼저 적용 조건과 문제 유사도가 기준을 넘은 후보만 남기고, 그 안에서 서로 다른 해결 원리를 섞습니다. 정렬 규칙과 가중치는 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;ranking_version&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;으로 고정합니다.&lt;br /&gt;
&lt;br /&gt;
외부 응답의 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;score&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;는 raw cosine이 아니라 0~1 범위의 서비스 점수입니다. 현재 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;find_analogies&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;의 lexical score 의미는 shadow 평가와 문서·테스트 변경 없이 조용히 바꾸지 않습니다. 의미 검색을 활성화할 때는 다음을 함께 적용합니다.&lt;br /&gt;
&lt;br /&gt;
* 고정 평가셋으로 서비스 점수를 보정&lt;br /&gt;
* 응답에 작은 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;ranking_version&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; 또는 동등한 진단 값 제공&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;basis&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;에 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;semantic_similarity&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;와 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;hybrid&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; 추가&lt;br /&gt;
* lexical 후보의 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;shared_terms&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; 유지&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;min_score&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;를 서비스 점수에 적용한다고 명시&lt;br /&gt;
=== 기준 저장소 재검증 ===&lt;br /&gt;
&lt;br /&gt;
후보를 받은 뒤 다음 순서로 확인합니다.&lt;br /&gt;
&lt;br /&gt;
# 후보 ID를 중복 제거하고 내부 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;scan_limit&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;까지만 유지합니다.&lt;br /&gt;
# MediaWiki에서 최신 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;LessonSnapshot&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;을 일괄 조회합니다.&lt;br /&gt;
# 없어진 페이지는 결과에서 빼고 인덱스 정리 대상으로 표시합니다.&lt;br /&gt;
# &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;retrieval_hash&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;가 달라진 semantic 후보는 결과에서 빼고 재색인합니다.&lt;br /&gt;
# 해시는 같고 리비전만 다르면 최신 Lesson을 사용합니다.&lt;br /&gt;
# 기존 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;SearchFilters&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;를 최신 Lesson에 다시 적용합니다.&lt;br /&gt;
# 안정적인 순서로 정렬한 뒤 페이지와 UTF-8 출력 제한을 적용합니다.&lt;br /&gt;
인덱스 지연으로 오래된 Lesson 내용이 반환되지는 않게 합니다. 대신 일부 semantic 후보가 잠시 빠질 수 있습니다. 이 경우 응답의 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;partial&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;을 참으로 표시합니다.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;scanned&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;는 인덱스 내부 ANN node 수가 아니라 기준 저장소 재검증 전에 서비스가 검토한 후보 ID 수로 정의합니다. &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;scan_limit&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;은 모든 후보 경로를 합친 엄격한 상한입니다.&lt;br /&gt;
&lt;br /&gt;
=== 인덱스 세대 ===&lt;br /&gt;
&lt;br /&gt;
다음 중 하나가 바뀌면 새 generation을 만듭니다.&lt;br /&gt;
&lt;br /&gt;
* 임베딩 모델 또는 artifact&lt;br /&gt;
* tokenizer&lt;br /&gt;
* 입력 정규화와 facet 구성&lt;br /&gt;
* token 예산 또는 chunk pooling&lt;br /&gt;
* 벡터 차원, 정규화 또는 거리 계산&lt;br /&gt;
* 순위 결합에 필요한 인덱스 구조&lt;br /&gt;
generation ID는 이 설정을 직렬화한 값의 불투명 해시로 만듭니다. 기존 인덱스를 제자리에서 덮어쓰지 않습니다.&lt;br /&gt;
&lt;br /&gt;
새 generation은 다음 순서로 활성화합니다.&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;BUILDING&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; 상태로 빈 generation을 만듭니다.&lt;br /&gt;
# MediaWiki recent changes의 high-water mark를 기록합니다.&lt;br /&gt;
# 전체 Lesson을 최대 50개씩 읽어 색인합니다.&lt;br /&gt;
# build 중 생긴 변경을 high-water mark 이후부터 다시 적용합니다.&lt;br /&gt;
# 누락, orphan, 리비전과 모델 구성을 검사합니다.&lt;br /&gt;
# shadow query로 현재 generation과 품질·지연 시간을 비교합니다.&lt;br /&gt;
# 검사를 통과하면 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;READY&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;로 바꾸고 active alias를 원자적으로 전환합니다.&lt;br /&gt;
# 이전 generation은 cursor 유효 기간과 rollback 기간 동안 최신 상태로 유지합니다.&lt;br /&gt;
# rollback 기간이 끝나면 이전 generation을 삭제합니다.&lt;br /&gt;
새 generation에 문제가 있으면 active alias만 이전 값으로 되돌립니다. 파생 볼륨이 손상되면 MediaWiki 리비전에서 다시 만듭니다.&lt;br /&gt;
&lt;br /&gt;
=== 페이지 나누기와 cursor ===&lt;br /&gt;
&lt;br /&gt;
의미 검색을 활성화하면 cursor에는 요청 fingerprint와 함께 generation을 넣습니다.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;v&amp;quot;: 2,&lt;br /&gt;
  &amp;quot;tool&amp;quot;: &amp;quot;find_analogies&amp;quot;,&lt;br /&gt;
  &amp;quot;fp&amp;quot;: &amp;quot;&amp;lt;request fingerprint&amp;gt;&amp;quot;,&lt;br /&gt;
  &amp;quot;gen&amp;quot;: &amp;quot;&amp;lt;retrieval generation&amp;gt;&amp;quot;,&lt;br /&gt;
  &amp;quot;pos&amp;quot;: 37,&lt;br /&gt;
  &amp;quot;exp&amp;quot;: 1780000000&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
fingerprint에는 query, filters, fields, &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;min_score&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;와 검색 전략을 포함합니다. generation이 cursor 유효 기간 안에 남아 있으면 같은 결과 순서를 이어서 반환합니다. 해당 generation을 더 이상 제공할 수 없으면 첫 페이지부터 다시 조회하라는 cursor 오류를 반환합니다.&lt;br /&gt;
&lt;br /&gt;
출력 byte 제한 때문에 페이지 끝의 결과를 빼면 cursor도 실제로 반환한 마지막 후보 까지만 이동합니다. 현재 v1 cursor는 기존 검색 경로에서 한시적으로 읽고, v2 전환은 MCP 문서와 테스트를 함께 바꿉니다.&lt;br /&gt;
&lt;br /&gt;
=== 동기화와 일관성 ===&lt;br /&gt;
&lt;br /&gt;
일관성 보장은 다음처럼 나눕니다.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! 항목 !! 보장&lt;br /&gt;
|-&lt;br /&gt;
| 반환한 Lesson 내용 || MediaWiki 최신 리비전으로 확인&lt;br /&gt;
|-&lt;br /&gt;
| 전체 텍스트 검색 || 저장 성공 뒤 바로 검색 가능&lt;br /&gt;
|-&lt;br /&gt;
| 의미 검색 완전성 || 짧은 지연을 허용하는 eventual consistency&lt;br /&gt;
|-&lt;br /&gt;
| relation 의미 || MediaWiki에 저장된 typed relation만 기준&lt;br /&gt;
|-&lt;br /&gt;
| 벡터 유사도 || 후보 추천이며 사실 또는 인과관계가 아님&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
MCP 쓰기는 항상 MediaWiki에 먼저 저장합니다. 성공 뒤 색인 갱신 힌트를 보내지만, 이 힌트가 실패해도 쓰기는 성공으로 처리합니다. recent changes poll과 전체 대조가 누락을 복구합니다.&lt;br /&gt;
&lt;br /&gt;
한 페이지의 임베딩이 반복해서 실패하면 제한된 횟수만 재시도합니다. 이후 해당 ID를 파생 오류 목록에 남기고 다음 변경 처리를 계속합니다. 한 페이지 때문에 전체 체크포인트가 멈추지 않게 합니다.&lt;br /&gt;
&lt;br /&gt;
=== 장애 동작 ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! 장애 !! 동작&lt;br /&gt;
|-&lt;br /&gt;
| query 임베딩 실패 || 전체 텍스트와 relation 후보로 fallback&lt;br /&gt;
|-&lt;br /&gt;
| 벡터 인덱스 연결 실패 || 전체 텍스트와 relation 후보로 fallback&lt;br /&gt;
|-&lt;br /&gt;
| 인덱스 지연 || hash가 다른 후보를 빼고 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;partial=true&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; 표시&lt;br /&gt;
|-&lt;br /&gt;
| 일부 Lesson 임베딩 실패 || 성공한 항목을 활성화하고 실패 ID만 재시도&lt;br /&gt;
|-&lt;br /&gt;
| 파생 볼륨 손상 || MediaWiki에서 새 generation 재구축&lt;br /&gt;
|-&lt;br /&gt;
| recent changes 누락 || 주기적 전체 대조로 복구&lt;br /&gt;
|-&lt;br /&gt;
| 모델과 인덱스 구성 불일치 || readiness 실패, generation 활성화 금지&lt;br /&gt;
|-&lt;br /&gt;
| 새 모델 품질 저하 || active alias를 이전 generation으로 rollback&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
semantic 검색 장애만으로 공개 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;/healthz&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;를 실패시키지 않습니다. 전체 텍스트 fallback이 가능하면 MCP는 읽기 서비스를 계속 제공합니다. 상세 semantic readiness는 내부 상태와 제한된 로그·지표로 확인합니다.&lt;br /&gt;
&lt;br /&gt;
=== 단계별 확장 ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! 단계 !! 구성 !! 다음 단계로 옮기는 기준&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 현재 전체 텍스트와 lexical analogy || 평가 기준선 확보&lt;br /&gt;
|-&lt;br /&gt;
| 1 || &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;mcp-http&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; 안의 immutable exact vector generation || 품질과 비용 검증&lt;br /&gt;
|-&lt;br /&gt;
| 2 || backend network 전용 검색 sidecar와 파생 volume || 재구축 시간, 메모리 또는 p95 지연 목표 초과&lt;br /&gt;
|-&lt;br /&gt;
| 3 || 공유 내부 검색 서비스와 여러 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;mcp-http&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; 인스턴스 || 가용성 또는 동시 요청 때문에 수평 확장 필요&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
단계 1에서는 서버가 먼저 전체 텍스트 검색을 제공하고, 백그라운드에서 새 immutable generation을 만든 뒤 포인터를 교체합니다. Lesson 수, 벡터 차원, 실제 메모리, 재구축 시간과 exact cosine p95를 측정합니다. 단순한 Lesson 수만으로 제품을 바꾸지 않습니다.&lt;br /&gt;
&lt;br /&gt;
단계 2의 검색 sidecar도 도메인 전용 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;search_candidates&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;와 내부 상태 확인만 제공합니다. 벡터 저장 제품의 포트를 호스트나 외부 네트워크에 열지 않습니다.&lt;br /&gt;
&lt;br /&gt;
단계 3에서는 색인기를 한 인스턴스만 실행하거나 lease로 조정합니다. 모든 MCP 인스턴스는 같은 active generation을 읽습니다. 외부에는 계속 중앙 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;/mcp&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; 주소 하나만 제공합니다. 현재 프로세스 메모리에 있는 인증 상태도 수평 확장 전에 공유 상태 또는 안전한 routing으로 바꿔야 합니다.&lt;br /&gt;
&lt;br /&gt;
=== 보안과 개인정보 ===&lt;br /&gt;
&lt;br /&gt;
임베딩은 익명화된 값이 아닙니다. 원문과 같은 민감도로 다룹니다.&lt;br /&gt;
&lt;br /&gt;
* 기본 선택은 서버 안이나 내부 네트워크의 다국어 임베딩 모델입니다.&lt;br /&gt;
* 외부 임베딩 API는 서버 담당자가 전송, 보존, 학습 사용, region과 비용 조건을 확인한 뒤 명시적으로 켭니다.&lt;br /&gt;
* 검색 query는 아직 위키에 저장하지 않은 민감한 문제를 포함할 수 있습니다.&lt;br /&gt;
* 원문 query와 Lesson 본문을 로그에 남기지 않습니다.&lt;br /&gt;
* 지표에는 generation, revision, 지연 시간, 결과 수와 오류 코드만 남깁니다.&lt;br /&gt;
* 벡터 인덱스는 backend network에서만 접근합니다.&lt;br /&gt;
* 별도 호스트를 쓰면 서비스 인증과 전송 암호화를 적용합니다.&lt;br /&gt;
* 색인기 계정은 Lesson 읽기에 필요한 최소 권한만 가집니다.&lt;br /&gt;
* 모델과 tokenizer artifact는 digest로 고정합니다.&lt;br /&gt;
* 페이지가 삭제되거나 접근 정책이 바뀌면 active와 rollback generation에서 모두 제거합니다.&lt;br /&gt;
공개 위키에 있는 Lesson도 외부 임베딩 제공자에게 전송해도 된다고 자동으로 간주하지 않습니다. 검색 query는 위키보다 더 민감할 수 있습니다.&lt;br /&gt;
&lt;br /&gt;
=== 관측 항목 ===&lt;br /&gt;
&lt;br /&gt;
다음 값을 query 원문 없이 측정합니다.&lt;br /&gt;
&lt;br /&gt;
* recent changes 지연 시간과 처리하지 않은 revision 수&lt;br /&gt;
* 마지막 poll과 전체 대조 시각&lt;br /&gt;
* 기준 Lesson 수와 generation별 색인 수&lt;br /&gt;
* missing, orphan, stale hash 수&lt;br /&gt;
* embedding, 후보 검색, MediaWiki 재조회와 재정렬 지연 시간&lt;br /&gt;
* fallback 비율과 원인&lt;br /&gt;
* hash 불일치로 제거한 후보 수&lt;br /&gt;
* query당 후보 수와 canonical filter로 제거한 수&lt;br /&gt;
* generation build 진행률, 실패, 재시도와 파생 오류 수&lt;br /&gt;
* active model, 입력 구성과 ranking version&lt;br /&gt;
* cursor 무효화와 출력 byte 제한 발생 비율&lt;br /&gt;
=== 품질 평가 ===&lt;br /&gt;
&lt;br /&gt;
벡터 검색은 기술적으로 동작하는 것만으로 활성화하지 않습니다. 한국어, 영어와 혼합 query를 포함한 작은 고정 평가셋을 먼저 만듭니다.&lt;br /&gt;
&lt;br /&gt;
다음 항목을 현재 검색과 비교합니다.&lt;br /&gt;
&lt;br /&gt;
* top 5 안에서 실제로 적용 가능한 후보 비율&lt;br /&gt;
* 다른 분야이지만 도움이 되는 후보 비율&lt;br /&gt;
* 저장된 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;analogous_to&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; relation의 회수율&lt;br /&gt;
* 정확한 오류 문자열과 고유 명칭 검색의 회귀 여부&lt;br /&gt;
* 같은 해결책이 반복되는 비율&lt;br /&gt;
* 근거와 적용 조건이 부족한 후보 비율&lt;br /&gt;
* p50, p95 지연 시간과 fallback 비율&lt;br /&gt;
평가용 query 원문에 비밀이나 개인 정보를 넣지 않습니다. 실제 사용 기록을 저장소에 그대로 커밋하지 않습니다. 새 generation은 품질 기준, 출력 제한과 장애 fallback 테스트를 모두 통과한 뒤 활성화합니다.&lt;br /&gt;
&lt;br /&gt;
=== 구현 순서 ===&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;LessonSnapshot&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;과 MediaWiki 일괄 조회를 추가합니다.&lt;br /&gt;
# 현재 동작을 감싼 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;RetrievalBackend&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;를 만들고 결과가 같은지 확인합니다.&lt;br /&gt;
# 고정 벡터를 쓰는 in-memory fake와 domain-level 테스트를 추가합니다.&lt;br /&gt;
# &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;ProjectionBuilder&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;, 교체 가능한 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;EmbeddingProvider&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;와 exact index를 추가합니다.&lt;br /&gt;
# 의미 결과를 반환하지 않는 shadow mode에서 품질과 비용을 측정합니다.&lt;br /&gt;
# &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;find_analogies&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;에 relation, lexical, semantic 결합을 적용합니다.&lt;br /&gt;
# 평가가 끝나면 &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;search_lessons&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;에 hybrid 검색을 적용합니다.&lt;br /&gt;
# 실제 지표가 전환 기준을 넘을 때만 sidecar 또는 공유 검색 서비스로 옮깁니다.&lt;br /&gt;
각 단계에서 기존 최대 20건, cursor, &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;partial&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;scanned&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;scan_limit&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;와 UTF-8 직렬화 상한을 유지합니다. 모델, 응답 또는 검색 정책이 바뀌면 MCP 모델, 예시와 문서를 함께 수정합니다.&lt;/div&gt;</summary>
		<author><name>S3Admin</name></author>
	</entry>
</feed>