MCP 서버를 사내 RAG 시스템에 직접 연결 성공

MCP라는 게 처음 나왔을 때는 솔직히 “또 새로운 표준 하나 더 생겼네” 싶었다. 표준이라는 게 너무 많이 생기다 보면 결국 안 쓰게 되는 경우가 많으니까. 그런데 막상 사내 RAG 시스템에 직접 붙여보니까 생각이 달라졌다. 설정 자체는 놀라울 정도로 간단했는데, 프로덕션 환경에 진짜로 올리려고 하니 그제서야 진짜 고민이 시작됐다.

이 글은 그 과정을 정리한 거다. MCP가 뭔지 설명하는 글은 이미 차고 넘친다. 그래서 개념 설명은 짧게만 짚고, 실제로 사내 시스템에 붙여보면서 뭐가 편해졌고 뭐가 여전히 막막했는지를 솔직하게 쓴다.

처음 붙여본 계기 – LangGraph 에이전트가 너무 많은 걸 직접 구현하고 있었다

내가 운영하던 LangGraph 에이전트는 사내 데이터를 조회하는 노드가 여러 개 있었다. 사내 문서 검색, 사용자 정보 조회, 특정 시스템 API 호출 같은 것들이었는데, 이 노드들을 다 직접 함수로 짜서 그래프에 박아넣는 구조였다. 문제는 이 함수들이 LangGraph 안에서만 쓸 수 있다는 거였다. 같은 사내 데이터를 다른 AI 도구, 예를 들어 Cursor나 Claude Desktop에서도 쓰고 싶을 때마다 똑같은 연동 로직을 다시 짜야 했다.

이게 비효율적이라는 걸 느끼던 차에 MCP를 다시 들여다봤다. MCP의 핵심 아이디어는 단순하다. 서버를 한 번 정의해두면 여러 AI 클라이언트에서 똑같이 가져다 쓸 수 있다는 것이다. 사내 검색 API를 MCP 서버로 한 번 노출시켜두면, LangGraph 에이전트에서도 쓰고 Claude Desktop에서도 쓰고 나중에 다른 도구가 생겨도 그대로 가져다 쓸 수 있다는 뜻이다. 이 재사용성이 가장 끌렸던 부분이다.

처음 붙이는 건 진짜 쉬웠다

사내 검색 API를 MCP 도구로 노출하는 첫 작업은 반나절도 안 걸렸다. fastmcp 같은 프레임워크를 쓰면 기존 API를 도구로 감싸는 작업이 거의 함수 데코레이터 수준으로 끝난다. 기존에 Swagger로 문서화돼 있던 API 스펙을 그대로 활용해서, 파라미터 스키마만 MCP 도구 정의에 맞게 옮기면 됐다.

테스트 환경에서 stdio transport로 띄워서 로컬에서 동작 확인하는 것까지는 정말 매끄러웠다. LangGraph 에이전트의 도구 목록에 이 MCP 서버를 등록하니까, 별도의 함수 작성 없이 에이전트가 바로 사내 검색을 호출할 수 있게 됐다. 기존에 직접 짰던 도구 함수 코드가 한 번에 정리되는 느낌이었다.

진짜 고민은 프로덕션에 올리면서 시작됐다

문제는 이걸 로컬 테스트가 아니라 실제 운영 환경에 올리려고 할 때부터였다. 로컬에서는 stdio transport로 별도 인증 없이 바로 동작했는데, 운영에서는 그럴 수가 없었다. 사내 시스템이고 여러 사람이 접근하는 환경이라 인증이 필수였다.

처음에는 이 부분을 가볍게 생각했다. 그런데 MCP 스펙 자체의 인증 부분이 이 시기에 계속 바뀌고 있었다. authorization 섹션이 한 번 재설계되는 시점과 맞물려서, 내가 참고하던 예제 코드 일부가 이미 구버전 스펙 기준이었다. 결국 OAuth 기반 인증으로 HTTP transport를 새로 구성하고, TLS 종단을 프록시 레이어에서 처리하는 구조로 다시 짜야 했다. 로컬에서 반나절 걸렸던 작업이, 프로덕션 인증 붙이는 데는 거의 일주일이 걸렸다.

장애 대응 – MCP 서버가 죽으면 에이전트가 갑자기 바보가 된다

운영하면서 가장 신경 쓰게 된 부분이 이거였다. MCP 서버가 잠깐이라도 응답을 안 하면, LangGraph 에이전트는 그 도구가 왜 실패했는지 제대로 이해하지 못하고 엉뚱한 답을 만들어내는 경우가 있었다. 사용자 입장에서는 에이전트가 갑자기 멍청해진 것처럼 느껴진다.

이 문제를 겪고 나서 헬스체크 엔드포인트를 따로 만들었다. MCP 서버에 /healthz 같은 경로를 추가하고, 외부 모니터링 도구로 주기적으로 핑을 날려서 장애를 빠르게 감지하도록 했다. 더 중요했던 건 degradation mode를 만든 거였다. 특정 도구가 실패하면 에이전트에게 단순히 에러를 던지는 게 아니라, “이 도구는 현재 사용할 수 없다”는 걸 구조적으로 알려주는 방식이다. 그러면 에이전트가 다른 경로로 우회하거나, 최소한 사용자에게 “지금 이 정보는 가져올 수 없다”고 솔직하게 답할 수 있다. 이걸 만들기 전에는 도구 실패가 에이전트의 환각으로 이어지는 경우가 종종 있었는데, degradation mode를 넣고 나서 이 문제가 확실히 줄었다.

데이터 신선도는 분명 장점이었다

좋았던 부분도 분명히 있다. 기존 RAG 파이프라인은 사내 문서를 미리 벡터화해서 인덱스에 넣어두는 구조였다. 문서가 업데이트되면 다시 임베딩하고 인덱스를 갱신하는 배치 작업이 필요했다. MCP로 사내 시스템을 직접 연결하니까, 이 전처리 과정 없이 실시간으로 최신 데이터를 가져올 수 있었다. 특정 사용자의 최신 주문 상태나 실시간으로 바뀌는 재고 정보처럼, RAG 인덱스로 미리 만들어두기 어려운 데이터에는 MCP 방식이 확실히 더 잘 맞았다.

다만 모든 데이터를 MCP로 옮기는 건 아니다. 정적인 문서, 자주 안 바뀌는 매뉴얼이나 정책 문서는 여전히 기존 RAG 인덱스로 두는 게 낫다. 매번 실시간으로 외부 API를 호출하는 것보다 미리 인덱싱해둔 게 응답 속도도 빠르고 비용도 적게 든다. 결국 데이터 성격에 따라 RAG 인덱스와 MCP 도구를 나눠 쓰는 게 맞는 답이었다.

다른 팀과 도구를 공유하면서 생긴 의외의 효과

MCP 서버를 한 번 만들어두니 예상 못 했던 효과도 있었다. 같은 사내 검색 도구를 다른 팀에서도 Claude Desktop이나 Cursor에 그대로 연결해서 쓰기 시작했다. 내가 LangGraph 에이전트를 위해 만든 도구가, 다른 개발자들의 일상적인 AI 어시스턴트 작업에도 그대로 재사용된 것이다. 이게 MCP가 약속하는 “한 번 만들면 여러 곳에서 쓴다”는 가치를 실제로 체감한 순간이었다.

다만 이게 동시에 책임도 늘었다는 뜻이다. 처음에는 내 에이전트 하나만 쓰는 도구였는데, 이제는 여러 사람과 여러 시스템이 의존하는 인프라가 됐다. 도구 하나를 수정하거나 스펙을 바꾸려면 거기 의존하는 모든 클라이언트에 영향을 주지 않는지 먼저 확인해야 한다. 가볍게 시작했던 게 어느새 운영 부담이 있는 시스템으로 커진 셈이다.

지금 시점에서 정리하는 솔직한 평가

MCP를 사내 시스템에 붙이는 작업 자체는 누구나 반나절 안에 해볼 수 있을 정도로 쉽다. 하지만 그걸 여러 사람이 의존하는 프로덕션 인프라로 운영하는 건 완전히 다른 차원의 작업이다. 인증, 장애 대응, 스펙 변경 대응까지 고려하면 일반적인 백엔드 API 하나를 운영하는 것과 똑같은 수준의 운영 역량이 필요하다.

그래도 결론적으로는 도입한 걸 후회하지 않는다. LangGraph 에이전트가 직접 구현하던 연동 로직들이 정리됐고, 데이터 신선도가 중요한 영역에서는 RAG로는 못 채우던 부분을 메웠다. 다만 처음 시작하는 사람에게는 분명히 말해주고 싶다. 로컬에서 도구 하나 만들어보는 것과, 그걸 여러 사람이 매일 의존하는 시스템으로 운영하는 것 사이에는 생각보다 큰 간극이 있다는 걸 미리 알고 시작하는 게 낫다.

Leave a Comment