Enterprise Knowledge Search
단일 진실 공급원의 꿈 대신, 데이터가 이미 사는 곳에서 만나라
핵심 개념
조직 안에서 정보를 찾는 일은 어렵다. 데이터는 도구마다 흩어져 있고, 분기마다 누군가 같은 기발한 해법을 제안한다 — 모든 걸 한 플랫폼에 기록해서 단일 진실 공급원을 만들자. 이 꿈은 실무에서 거의 통하지 않는다.
정보는 편리하고 자연스러운 곳에서 생성되기 때문이다. 문서의 수정 제안, Slack 스레드, GitHub의 코드 참조, Jira의 상태 메타데이터. 이 플랫폼들은 각자의 도메인을 위해 수년간 최적화되었다. PR 논의를 Google Docs에서 하는 건 끔찍한 경험이다.
따라서 설계 원칙이 뒤집힌다: 기존 행동을 최소한으로 바꾸고, 각 플랫폼에서 직접 데이터를 추출한다.
아키텍처 — 하나의 테이블, 소스당 하나의 커넥터
지식 베이스가 제공하는 것은 세 가지다.
- 사내 데이터를 수집·저장하는 플랫폼
- 그 데이터를 질의하는 플랫폼
- 인증·인가를 강제하고 감사·분석을 붙이는 레이어
핵심은 단일 임베딩 테이블(Postgres 한 테이블에 embedding, raw summary, metadata)이다.
SLACK ────────┐
WIKI ─────────┤
CODE REPOS ───┼──> [ 하나의 embeddings 테이블 ]──> MCP / Web UI / Agents
NETLISTS ─────┤ document · embedding
PRD DOCS ─────┤ metadata · source + timestamps
CUSTOM DBs ───┘
소스마다 정의하는 것은 세 가지뿐이다 — 데이터가 무엇인지, 어떻게 연결하는지, 얼마나 자주 가져오는지. 결과 row는 출처와 무관하게 같은 인터페이스를 따른다. 그래서 다른 팀도 커스텀 커넥터를 만들 수 있다: 자기 시스템을 읽어 같은 스키마의 row를 뱉는 작은 모듈을 PR로 올리면 나머지 스택은 변경 없이 동작한다.
벡터 검색만으로는 안 되는 이유
Slack 같은 비정형 대화 데이터에서 순수 임베딩은 무너진다.
- 정보 밀도 편차가 극심하다 — “hey yeah sure mike”와 상세한 커널 설명이 둘 다 하나의 메시지다
- 짧은 메시지가 코사인 유사도에서 길고 상세한 메시지를 자주 이긴다
- 메시지의 의미가 주변 대화에 의존한다
하이브리드 4종 — 서로의 약점을 메운다
| 기법 | 무엇을 잡나 |
|---|---|
| full-text | 임베딩이 뭉개는 정확한 토큰 — 에러 문자열, 플래그 이름, 호스트명. 엔지니어가 문자 그대로의 에러를 붙여넣으면 어떤 의미 유사도도 정확한 어휘 매치를 이겨서는 안 된다 |
| embedding | 패러프레이즈. “restore hangs after manifest load”와 “checkpoint stalls on the NFS mount”는 어휘를 공유하지 않을 수 있다 |
| IDF | 신호와 잡음의 분리. 희귀 토큰 중심의 짧은 메시지는 순위에 올라야 하고, “sounds good, thanks!”는 임베딩 공간에서 많은 쿼리에 가깝지만 term rarity를 고려하면 0에 가깝다 |
| age decay | 답변은 만료된다. 두 스레드가 같은 질문에 답할 때 6개월 전 것은 더 이상 없는 인프라를 설명할 수 있다 |
어떤 스코어러도 단독으로 신뢰되지 않는다. 각각이 같은 코퍼스에 대한 자기 랭킹 뷰를 만들고 쿼리 시점에 융합된다.
Distillation — 원문을 그대로 임베딩하지 않는다
LLM이 전체 스레드에서 구조화 데이터를 추출한다.
- 엔지니어가 실제로 검색할 법한 한 줄 질문
- 짧은 요약
- resolution (해결책)
- 언급된 시스템·코드 참조
원본 트랜스크립트는 직접 임베딩하지 않는다. 일관된 포맷으로 정규화했을 때 정확도가 유의미하게 올랐고, 추가 메타데이터가 의미 매치에 더 나은 신호를 준다. 원시 텍스트는 full-text(GIN) 인덱스로 랜딩 즉시 키워드 검색 가능하다.
Bursting — 요약이 놓친 것을 살리기
긴 스레드 안의 중요한 메시지가 스레드 레벨 요약에 항상 담기지 않는다. burst = 같은 작성자의 연속 메시지 묶음을 스레드 주제를 컨텍스트로 앞에 붙여 별도로 임베딩한다. 답이 어휘가 요약에 전혀 안 들어간 곁가지 메시지 하나에 있을 때 그것을 독립적으로 찾을 수 있게 된다.
저신호 데이터를 막는 임계 조합: 코퍼스 전반 IDF ≥ 4.0의 희귀 토큰 포함, 결합 200자 이상, 리액션이 있으면 소셜 부스트.
스레드 단위 재수집 — 갱신 모델
메시지 이벤트를 받으면 그 메시지만 저장하지 않는다. 속한 스레드를 해석해 부모와 모든 답글을 포함한 전체 대화를 다시 가져와 한 row로 쓴다. 그래야 저장된 내용·참여자 목록·마지막 활동 타임스탬프가 항상 완전한 대화를 반영한다.
채널(또는 소스)마다 자기 데이터 소스라서 바쁜 인시던트 채널은 더 자주 수집하는 식으로 신선도를 세밀 조정할 수 있다.
코드 — “grep is all you need”인가
CLI 코딩 에이전트의 부상으로 코드 임베딩은 반직관적으로 느껴진다. 그럼에도 시맨틱 검색이 값어치를 하는 이유는 위와 같다 — 어휘를 공유하지 않는 질문과 답을 잇는다.
- 언어별 경계를 거친 것에서 세밀한 것 순으로 적용: 클래스 같은 상위 경계를 먼저 시도하고, 청크가 여전히 크면 메서드 경계, 그다음 더 작은 블록. 파일 하나가 파일 레벨·함수 레벨 등 여러 특이도의 임베딩을 생성
- 커밋마다 바뀐 청크만 재임베딩. 동기화 상태와 임베딩 스토어가 같은 DB에 사는 것이 특히 잘 맞는다
- 리포 온보딩을 팀이 직접 제출하는 설정 파일로(파일 경로 레벨 allowlist/denylist 포함)
Planner → Executor → Synthesis
쿼리마다 짧은 플래닝 패스에서 LLM이 어떤 툴·소스가 중요할지 결정한다. 플래너가 보는 것은 무엇이 인덱싱되어 있는지에 대한 컴팩트한 설명 — 어떤 프로젝트가 있는지, 각 프로젝트에 어떤 소스가 있는지, 그리고 결정적으로 각 소스가 무엇에 답하기 좋은지.
그다음 executor가 툴 콜을 병렬 팬아웃하고, 결과를 점수·최신성·소스 힌트를 담은 공유 evidence 스키마로 정규화하고, 최종 synthesis LLM이 인용·주의사항과 함께 답변을 만든다.
Reranking — RRF + 컨텍스트 복원
문서는 다른 질문에 답하면서 단지 쿼리와 어휘를 공유한다는 이유로 상위에 뜰 수 있다.
- RRF (reciprocal rank fusion) — 서로 호환되지 않는 리스트들을 합친다. 문서마다 등장한 각 리스트에 대해
weight / (60 + rank)를 더한다. 스무딩 상수가 단일한 강한 투표보다 합의를 더 중요하게 만든다 — 여러 리트리버에서 상위에 뜬 문서가 하나에서만 1위인 문서를 이길 수 있다 - 중복 청크를 소스 단위로 병합하고 파일당 기여 결과 수를 캡해 더 다양한 top 20
- 작은 리랭커 모델이 원 쿼리와 후보를 받아 0~10점을 매기고 top 10을 남긴다
- 랭킹이 끝난 뒤 승자에게 컨텍스트를 되돌려준다 — 위키 섹션이 매치되면 인접 두 섹션을 끌어와 청킹이 분리해버린 제목·전제조건·주의사항을 복원. 중요한 맥락이 빠진 외로운 문단 대신 완결된 스니펫을 준다
MCP vs UI — 오케스트레이션을 누가 소유하는가
같은 검색 레이어를 두 방식으로 노출할 수 있다.
MCP — 검색 프리미티브를 하나의 “이 질문에 답해줘” 엔드포인트 뒤에 숨기지 않고 직접 툴로 노출한다. 툴은 의도적으로 단순하고 가능한 한 LLM-free해서 클라이언트가 빠르고 싸게 질의할 수 있다. 입출력은 좁고 구조화되고 안정적이라 어떤 클라이언트·에이전트에서도 추가 오케스트레이션 로직 없이 부를 수 있다. 에이전트가 오케스트레이션 엔진이 되고, 검색 레이어는 요청을 서빙하기 위해 그 LLM 결정에 의존하지 않는다. → MCP (Model Context Protocol)
Web UI — 같은 툴 위에 완전한 파이프라인(planner → executor → synthesis)이 얹힌다. 사용자에게는 “질문하면 답이 나온다”이지만 내부적으로는 MCP 클라이언트가 명시적으로 재현할 수 있는 것과 같은 패턴이다.
Projects — 검색 범위가 곧 관련성
코퍼스가 커지면 “모든 곳에서 모든 것을 검색”이 급속히 무용해진다. 컴파일러 팀 엔지니어는 결과에 인프라 런북이 나오길 원하지 않는다.
project = 이름 붙은 데이터 소스 묶음(특정 채널, 리포, DB, 문서 공간). 의도적으로 가볍게 만들어 같은 소스를 복제하지 않고 여러 프로젝트가 참조할 수 있게 한다.
온보딩 때 기본 프로젝트를 고르게 해 프로필에 저장하고 쿼리를 자동 스코핑하면, 신규 인원이 어떤 채널·리포·문서 공간이 중요한지 먼저 배우지 않고도 고신호 답변을 받는다.
연관 개념
- RAG
- MCP (Model Context Protocol)
- Knowledge Representation
- Multimodal Search
- Context Engineering
- AI Agent
- Semantic Layer