본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 06. 25. 15:32

통합 MCP 지식 서버 구축하기: 6개의 서로 다른 지식 베이스를 Claude Desktop에 연결하는 방법 (그리고 무엇이 망가졌는가)

요약

Model Context Protocol(MCP)을 사용하여 Markdown, Confluence, Jira, GitHub 등 6개의 서로 다른 지식 베이스를 Claude Desktop에 통합하는 방법을 다룹니다. Java Spring Boot를 활용한 아키텍처 구현 방식과 구축 과정에서 겪은 컨텍스트 윈도우 관리 등의 실무적 교훈을 공유합니다.

핵심 포인트

  • MCP를 통해 다양한 데이터 소스를 단일 인터페이스로 통합 가능
  • Java Spring Boot를 이용한 간단한 프로바이더 패턴 구현
  • 검색 결과가 너무 많을 경우 Claude의 컨텍스트 윈도우 초과 위험
  • 다양한 지식 소스 통합 시 데이터 집계 및 관리의 중요성

통합 MCP 지식 서버 구축하기: 6개의 서로 다른 지식 베이스를 Claude Desktop에 연결하는 방법 (그리고 무엇이 망가졌는가)

솔직히 말해서, 이게 정말 작동할 줄은 몰랐습니다.

Papers라고 불리는 저의 1,800시간짜리 실패한 지식 베이스 프로젝트에 관한 76개의 글을 쓴 끝에, 저는 마침내 미친 짓을 시도했습니다. 바로 단일 MCP (Model Context Protocol) 서버를 통해 6개의 완전히 다른 지식 소스를 Claude Desktop에 연결하는 것이었습니다. Markdown 노트부터 Confluence 페이지, Jira 티켓, GitHub 이슈까지 모든 것이 포함되었습니다.

결과는 어땠을까요? 예상보다 훨씬 더 잘 작동했습니다. 하지만 그 과정에서 엄청난 문제들이 발생하기도 했습니다.

제가 무엇을 만들었는지, 무엇을 망가뜨렸는지, 그리고 무엇을 배웠는지 설명해 드리겠습니다. 만약 여러분이 자신만의 MCP 지식 서버를 구축할 생각을 하고 있다면, 이것은 아무도 미리 말해주지 않는 내용들입니다.

문제점: 나의 지식은 이미 사방에 흩어져 있었다

상황은 이렇습니다. 저는 지식 수집광입니다. 제 노트는 여기저기 흩어져 있습니다:

  1. 개인 Markdown 노트 (Papers 내 약 2,800개 파일)
  2. 회사 Confluence (네트워크 외부로 나갈 수 없는 내부 문서)
  3. Jira 티켓 (엔지니어링 프로젝트 계획)
  4. GitHub 이슈 (오픈 소스 프로젝트 추적)
  5. Google Drive 문서 (공유된 회의록)
  6. 북마크 (나중에 읽으려고 저장해둔 기사들)

MCP 이전에는 Claude가 여러 소스에 걸친 질문에 답하게 하려면, 각 장소에서 수동으로 복사하여 붙여넣어야 했습니다. 고통스럽고 느렸죠. 심지어 그런 정보가 존재한다는 사실조차 절반은 잊어버리곤 했습니다.

저는 MCP가 이 문제를 해결할 수 있다고 생각했습니다. 하나의 표준화된 인터페이스. Claude가 질문을 던지면, 제 서버가 지식을 찾아내는 방식입니다. 모두가 행복해지는 거죠.

그렇지 않나요?

아키텍처: 하나의 서버, 다수의 프로바이더 (Providers)

아키텍처는 생각보다 간단하게 마무리되었습니다. MCP는 데이터가 어디에서 오는지 상관하지 않습니다. 단지 tools/listtools/call을 올바르게 구현하기만 하면 됩니다.

핵심 Java Spring Boot 구현체는 다음과 같습니다:

// KnowledgeProvider.java - 모든 소스를 위한 공통 인터페이스
public interface KnowledgeProvider {
    String getName();
...

그 후 메인 MCP 컨트롤러(controller)는 모든 프로바이더(provider)에게 작업을 위임하고 결과를 집계(aggregate)하기만 하면 됩니다:

// MCPServerController.java
@RestController
@RequestMapping("/mcp")
...

그게 전부입니다. 코드 약 150줄 정도입니다. 전체 과정이 매우 단순합니다.

무엇이 망가졌는가: 고생하며 배운 6가지 교훈

저는 주요 과제가 인증(authentication)이나 검색 정확도(search accuracy)에 있을 것이라고 생각했습니다. 아니었습니다. 저를 힘들게 했던 문제들은 완전히 예상치 못한 것들이었습니다.

1. 컨텍스트 윈도우 지옥 (Context Window Hell): 결과가 Claude의 컨텍스트를 잡아먹다

솔직히 이 부분은 저를 놀라게 했습니다. 저는 "결과가 많을수록 = 더 나은 답변"이라고 생각했습니다. 틀렸습니다.

6개의 지식 프로바이더(knowledge provider)를 통해 검색하면 쉽게 50개 이상의 결과가 나올 수 있습니다. 각 결과의 전체 내용(full content)을 모두 보낸다면, Claude의 100k 컨텍스트 윈도우(context window) 중 50k 토큰을 순식간에 써버리게 됩니다. Claude는 결과물에 파묻혀서 정작 질문에 답변할 수 없게 됩니다.

해결책: 검색 시 스니펫(snippet)과 메타데이터(metadata)만 반환하세요. Claude가 실제로 관심 있는 결과의 전체 내용을 _명시적으로 요청(explicitly ask)_하도록 만드세요.

// 이전: 나쁜 방식 - 전체 내용을 전송
public record KnowledgeResult(
    String id,
...

이제 Claude는 검색 결과를 훑어보고, 관련 있어 보이는 2~3개를 선택하여 그것들만 가져올 수 있습니다. 컨텍스트를 엄청나게 절약할 수 있습니다. 게임 체인저(game changer)입니다.

2. 서로 다른 검색 패턴에는 서로 다른 도구가 필요하다

처음에는 search_knowledge라는 도구 하나만 있었습니다. 단순한 쿼리(query)에는 작동했지만, 더 복잡한 질문에는 처참하게 실패했습니다.

문제는 무엇이었을까요? 지식 소스(knowledge source)마다 서로 다른 검색 접근 방식이 필요하다는 것이었습니다. Jira 티켓을 검색하는 것은 Markdown 노트를 검색하는 것과 같지 않습니다.

해결책: 각 소스 유형별로 여러 개의 도구(tool)를 노출하세요. Claude가 어떤 것을 사용할지 결정하게 하세요:

  • search_all_knowledge - 모든 소스 대상 (광범위한 질문에 유용)
  • search_personal_notes - 나의 Markdown 파일만 대상
  • search_confluence - 내부 문서만 대상
  • search_jira - 프로젝트/상태별 필터링 포함
  • search_github - 이슈(issues) 및 PR(Pull Requests) 대상

결과적으로 Claude는 질문에 적합한 도구를 선택하는 데 상당히 능숙하다는 것이 밝혀졌습니다. 만약 제가 "지난 성능 회의의 결론이 무엇이었나요?"라고 물으면, Claude는 자동으로 Confluence를 검색합니다. 만약 "MCP 에러 핸들링에 대해 내가 뭐라고 썼지?"라고 물으면, 개인 메모를 검색합니다.

3. CORS Preflight는 인증을 위해 특별한 처리가 필요함

지난 글에서 MCP 인증(authentication)에 대해 썼던 것을 기억하시나요? 이번 문제는 저를 다시 한번 괴롭힌 구체적인 고충(pain point)이었습니다.

Claude Desktop에서 연결할 때, 실제 요청을 보내기 _전(before)_에 OPTIONS 프리플라이트(preflight) 요청을 보냅니다. 그런데 결과가 어땠을까요? 프리플라이트 요청에는 API 키를 보내지 않습니다.

만약 필터가 인증되지 않은 OPTIONS 요청을 거부한다면, 전체 연결이 실패합니다. CORS가 깨지는 것이죠. Claude는 아예 연결할 수 없게 됩니다.

해결책: CORS를 위해 인증되지 않은 OPTIONS 요청은 항상 허용하세요:

// McpCorsConfig.java - Java Spring Boot 예시
@Configuration
public class McpCorsConfig implements WebMvcConfigurer {
...

그게 전부입니다. 단 세 줄의 설정으로 이 문제가 해결되었습니다. Postman에서는 잘 작동하는데 왜 Claude Desktop은 연결되지 않는지 디버깅하며 보낸 3시간을 아낄 수 있었습니다.

4. 서드파티 속도 제한(Rate Limits)이 당신을 망칠 것이다

GitHub, Google Drive, Confluence 등에서 데이터를 가져올 때 — 이들 모두에는 속도 제한(rate limits)이 있습니다. 모든 제공자(provider)를 대상으로 병렬 검색을 수행하면, 생각보다 훨씬 빠르게 이 제한에 도달할 수 있습니다.

한번은 검색을 수행했는데 30초 만에 GitHub 속도 제한에 걸린 적이 있습니다. 다시 작동할 때까지 한 시간을 기다려야 했습니다. 별로 좋은 경험은 아니었죠.

해결책: 제공자별 속도 제한(per-provider rate limiting)과 우아한 성능 저하(graceful degradation)를 추가하세요. 한 제공자가 속도 제한에 걸리더라도, 전체 검색을 실패시키는 대신 다른 제공자들의 결과라도 반환해야 합니다.

// RateLimitedKnowledgeProvider.java - wrapper 예시
public class RateLimitedKnowledgeProvider implements KnowledgeProvider {

...

우아한 성능 저하(Graceful degradation)는 당신의 친구입니다. 사용자들은 하나의 API가 속도 제한에 걸렸다는 이유로 아무 결과도 받지 못하는 것보다, 일부 결과라도 받는 것을 훨씬 선호할 것입니다.

5. 콘텐츠 포맷팅은 MCP 친화적이어야 함

MCP 응답은 단순한 텍스트입니다. 하지만 서로 다른 소스에서 콘텐츠를 가져올 때, 각기 다른 포맷을 가지고 있습니다:

  • Confluence는 Storage Format (HTML)을 사용합니다.
  • Jira는 Wiki markup을 사용합니다.
  • Markdown은... 음, 마크다운이죠.
  • Google Docs는 일반 텍스트 (plain text)로 내보내집니다.

Claude에게 가공되지 않은 HTML을 그대로 보내면 작동은 하지만, 수많은 div, class, 인라인 스타일(inline styles) 때문에 혼란을 겪습니다. 콘텐츠 대신 마크업 자체에 주의를 기울이기 시작하는 것입니다.

해결책: MCP로 보내기 전에 모든 것을 공통된 Markdown으로 정규화(Normalize)하세요. 저는 각 소스별로 간단한 변환기(converter)를 작성했습니다:

// HtmlToMarkdown.java - commonmark-java 사용
public class HtmlToMarkdown {
    public static String convert(String html) {
...

깔끔한 Markdown은 용량이 더 작고 깨끗하며, Claude가 완벽하게 이해합니다. 불필요한 찌꺼기(cruft)가 없습니다.

6. 어떤 제공자(Providers)는 가치를 더하지 못함 (그리고 그것은 괜찮음)

6개의 제공자를 모두 구축한 후, 한 달 동안 실제로 사용해 보았습니다. 결과가 어땠을까요? 그중 두 개는 거의 사용되지 않았습니다.

제 Google Drive 연동은 기술적으로는 작동하지만, Google Drive 문서에 대해 질문하는 일은 거의 없습니다. 그 내용 대부분은 더 이상 필요하지 않은 몇 달 전의 회의록입니다. 북마크(bookmarks)도 마찬가지입니다. 나중에 읽기 위해 사용하지만, Claude를 통해 검색해야 할 일은 드뭅니다.

해결책: 모든 것을 연결해야 한다는 압박감을 느끼지 마세요. 실제로 매일 검색하는 소스부터 시작하세요. 정말 필요할 때만 더 추가하세요.

한 달 후 저의 현재 사용량 분석입니다:

  • 개인 Markdown 노트: 검색의 65%
  • Confluence: 20%
  • Jira: 10%
  • GitHub Issues: 4%
  • 기타 모두 합계: 1%

솔직히 말해서, 다시 한다면 저는 개인 노트와 Confluence로만 시작했을 것입니다. Jira는 나중에 추가했을 것이고, 나머지는 실제로 필요할 때까지 건너뛰었을 것입니다. 덕분에 일주일의 작업 시간을 아꼈을 것입니다.

장단점: 솔직해져 봅시다

장점 ✅

  1. 그냥 됩니다 (It just works) — 초기 설정의 골칫거리만 넘어서면, Claude Desktop은 여러분의 모든 지식과 함께 그냥 작동합니다. 질문을 하면, 자동으로 검색하고, 필요한 것을 가져와서, 답변합니다. 마법처럼 느껴집니다.

  2. 개인정보 보호 우선 (Privacy first) — 모든 데이터는 여러분의 서버에 머뭅니다. Claude는 요청한 특정 스니펫(snippets)만 가져갑니다. 지식 베이스 전체를 클라우드에 업로드할 필요가 없습니다. 네트워크를 벗어날 수 없는 사내 내부 문서에 완벽합니다.

  3. 표준 프로토콜 = 미래 보장 (Standard protocol = future proof) — MCP를 한 번 구현해 두면, MCP 호환되는 모든 클라이언트에서 작동합니다. Claude Desktop은 이미 이를 지원합니다. 다른 클라이언트들도 지원을 추가하고 있습니다. 새로운 AI 어시스턴트가 나올 때마다 매번 다시 통합할 필요가 없습니다.

  4. 조립 가능 (Composable) — 새로운 지식 소스를 추가하고 싶나요? 그냥 KnowledgeProvider 인터페이스를 구현하면 됩니다. 끝입니다. 다른 어떤 것도 변경할 필요가 없습니다.

단점 ❌

  1. 여전히 호스팅이 필요함 — Claude Desktop이 연결하려면 MCP 서버가 공개적으로 접근 가능해야 합니다. 로컬에서 실행 중이라면 개발을 위해 ngrok이 필요합니다. 24시간 내내 접근하려면 어딘가에 호스팅해야 합니다. 배포 옵션에 대해서는 지난 글에서 작성했습니다.

  2. 내장된 캐싱 없음 — 모든 검색이 라이브 API를 호출합니다. Confluence가 느리면 검색도 느려집니다. 자체적인 캐싱(caching)을 추가해야 합니다. 저는 검색 결과를 15분 동안 캐싱하는데, 제 사용 사례에서는 꽤 잘 작동합니다.

  3. 속도 제한 (Rate limits)은 실재함 — 위에서 언급한 내용과 같습니다. 타사 API를 통합하는 경우, 결국 속도 제한에 걸리게 됩니다. 이에 대한 계획을 세우세요.

  4. MCP는 아직 초기 단계임 — 프로토콜이 진화하고 있습니다. 일부 클라이언트 동작은 아직 다소 거칠 수 있습니다. 변화가 생길 것을 예상하세요. 그렇긴 해도, 개인 프로젝트용으로는 이미 충분히 사용 가능합니다.

다시 하겠는가?

당연합니다.

저를 포함해 사실상 아무도 사용하지 않았던, 과하게 설계된 (over-engineered) 이 지식 베이스를 6년 동안 구축해 온 끝에, MCP 덕분에 마침내 유용해졌습니다. 저는 매일 Claude Desktop을 사용하여 제 자신의 지식에 관한 질문에 답합니다. 마치 제 모든 노트를 읽은 연구 보조원을 둔 것 같습니다.

놀라운 점이 무엇인지 아십니까? 지식 제공자(knowledge providers)를 갖춘 후, 이를 작동시키는 데 단 150줄의 코드만 필요했다는 것입니다. 그게 전부입니다. 모든 힘든 작업은 지난 6년 동안 지식을 수집하는 과정에서 이미 끝났습니다. MCP는 단지 그것을 AI에 연결했을 뿐입니다.

이 모든 MCP 실험을 통해 제가 얻은 가장 큰 교훈은 다음과 같습니다:

AI가 "AI-ready" 상태가 되기 위해 Hacker News에서 읽을 법한 화려한 임베딩 (embeddings), 벡터 데이터베이스 (vector databases) 같은 쓰레기들이 필요한 것은 아닙니다.

AI에게는 그저 _검색 (search)_하고 _검색 결과 추출 (retrieve)_할 수 있는 표준적인 방법이 필요할 뿐입니다. 이해는 AI가 합니다. 당신은 그저 AI에게 당신의 데이터에 접근할 권한을 주기만 하면 됩니다.

제 전체 검색 구현은 기본적으로 string.contains()를 강화한 형태입니다. 화려한 벡터 임베딩 (vector embeddings)도 없고, 비용이 많이 드는 LLM 재순위화 (reranking)도 없습니다. 그저 제 모든 노트에 대한 단순한 전체 텍스트 검색 (full-text search)일 뿐입니다. 그리고 이것은 제가 6년 전에 구축했던 화려한 2,000줄짜리 구현체보다 더 잘 작동합니다.

단순함이 승리합니다. 이번에도 말이죠.

여러분의 차례

여러 가지 지식 소스를 통합하는 MCP 서버를 구축해 보셨나요? 무엇이 놀라웠나요? 저와 같은 CORS/preflight 문제를 겪으셨나요, 아니면 다른 문제를 발견하셨나요?

아래에 댓글을 남겨 여러분의 경험을 공유해 주세요. 저도 여전히 이 기술을 배우는 중이며, 여러분에게 무엇이 효과적이었는지 듣고 싶습니다.

전체 코드를 보고 싶다면 GitHub에서 프로젝트를 확인하세요 👇

https://github.com/kevinten10/Papers

즐거운 빌딩 되세요!

AI 자동 생성 콘텐츠

본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0