MCP 소개

오다혜·2025년 5월 31일
post-thumbnail

1. MCP 란

MCP 란 Model Context Protocol 의 약어로, 애플리케이션이 LLM에 컨텍스트(정보)를 제공하는 방식을 표준화하는 개방형 프로토콜입니다. AI모델 Claude를 만든 회사인 Anthropic 에서 처음 발의한 개념으로, AI 시스템과 데이터 소스를 연결하기 위한 표준 규격을 뜻합니다. MCP를 사용하면 결과적으로 LLM 시스템이 필요한 데이터에 액세스할 수 있는 더 간단하고 안정적인 방법을 제공합니다.

Claude, ChatGPT, Cursor, Perplexity 등 최근에 다양한 LLM host 들이 등장하고 있습니다. 초창기에는 각 host 마다 연결하는 통신 규격이 정해져 있지 않아서, 외부 시스템과 연동을 위해서는 데이터 원천/외부 시스템(M개)와 host(N개)의 곱(M * N) 만큼의 연결 서버를 만들어야 하는 번거로움이 있었습니다.

MCP는 이 과정을 표준화해서 각 외부 시스템마다 MCP 서버만 만들고, 각 애플리케이션마다 MCP 클라이언트만 만들면 되도록 구조를 단순화합니다. LLM host 개발자들은 MCP 규격에 맞게 MCP Client 를 개발/제공하고 LLM 사용자들은 MCP Server 만 만들게 되어 통합 난이도가 M+N 문제로 줄어들었으며 여러 MCP Client 와 한 번에 연결할 수 있게 되었습니다.

2. MCP 의 특징과 장점

  • 양방향 통신: 단순 API 호출이 아니라, AI와 외부 시스템이 지속적으로 정보를 주고받음.

  • 보안과 권한 관리: OAuth2.0, JWT 등 기존 인증 체계와 연동. 각 연결마다 명확한 권한과 보안 경계 설정.

  • 확장성: 오픈소스, 커뮤니티 기반. 누구나 새로운 MCP 서버(도구) 개발 가능.

  • 표준화: 하나의 MCP 인터페이스로 다양한 데이터 소스/도구 연결, 코드 재사용성 극대화

MCP 가 없을 때

  • 각각의 외부 시스템(API)과 직접 통합해야 하므로, 시스템마다 다른 엔드포인트, 파라미터, 인증 방식 등을 모두 따로 구현해야 함.
  • 새로운 시스템을 추가할 때마다 별도의 커스텀 코드를 작성해야 하며, 여러 API를 연결할수록 복잡도가 기하급수적으로 증가함.
  • API의 사소한 변경(필드명, 버전 등)에도 클라이언트 코드가 쉽게 깨지고, 유지보수 부담이 큼

MCP 가 있을 때

  • 표준화된 MCP 프로토콜만 구현하면, 다양한 외부 시스템을 동일한 방식으로 연결할 수 있음.
  • “한 번 작성, 여러 번 통합”이 가능해져 개발 및 유지보수 효율이 극대화됨.
  • 새로운 데이터 소스나 도구를 추가할 때도 MCP 서버만 연결하면 되므로 확장성이 뛰어남

3. MCP 구조

동작 예시

  1. Host(예: Claude Desktop)가 시작되면 여러 MCP Client를 생성하고, 각 Client는 MCP Server와 연결합니다.
  2. Client는 서버가 제공하는 기능(도구, 리소스, 프롬프트 등)을 질의하여 목록을 받습니다.
  3. 사용자가 요청(예: “이 GitHub 저장소의 오픈 이슈 목록 알려줘”)을 입력하면, Host는 적절한 MCP Client를 통해 MCP Server에 요청을 보냅니다.
  4. Server는 외부 API나 데이터베이스에서 정보를 가져와 결과를 Client에 반환합니다.
  5. Client는 Host에 결과를 전달하고, Host는 이를 LLM의 컨텍스트에 추가하여 최종 응답을 생성합니다

4. MCP 의 단점

GPT는 stateless, 즉 상태를 저장하지 않는 모델입니다. 서버나 모델 자체가 과거 대화를 기억하지 않기 때문에, 우리가 봤을 때 자연스럽고 일관된 대화를 만들기 위해서는 모든 대화 내역을 매번 요청에 함께 보내야 합니다.

이로 인해 아래의 문제가 발생합니다.

토큰 비용과 속도

요청에 포함되는 메시지가 많아질수록 전체 입력 토큰 수가 늘어나게 되고, 이에 따라 응답 속도가 느려지고 비용도 증가하게 됩니다. 특히 GPT-4 같이 고성능 모델의 경우 입력 토큰에 따라 요금이 달라지므로, 대화가 길어질수록 부담이 커집니다.

보안과 개인정보 이슈

사용자가 민감한 정보를 다루는 경우, 매번 전체 메시지를 포함해서 전송한다는 점이 보안상 취약점이 될 수 있습니다. 이를 해결하려면 프론트엔드 또는 백엔드에서 컨텍스트를 잘 관리하고, 필요 시 민감한 내용을 요약하거나 마스킹하는 등의 처리가 필요합니다.

구현 난이도

초보자 입장에서 보면 단순히 질문만 보내는 것이 아니라, 시스템 프롬프트부터 이전 대화까지 포함해서 메시지 배열을 구성해야 하므로, 구조화된 프로토콜 설계가 필요합니다. 특히 멀티턴(Multi-turn) 챗봇을 만들 경우, 대화 기록을 요약하거나 압축하는 로직도 함께 고려해야 합니다.

5. 프론트에서 MCP 와 통신하기

구조

/src
  ├── models/gpt.ts            ← Model: GPT 호출
  ├── contexts/ChatContext.tsx ← Context: 메시지 관리
  ├── protocols/message.ts     ← Protocol: 메시지 타입 정의
  └── App.tsx                  ← View: UI 구성

protocols/message.ts (Protocol 정의)

export type Role = "user" | "assistant" | "system";

export interface ChatMessage {
  role: Role;
  content: string;
}

models/gpt.ts (Model 호출)

import { ChatMessage } from "../protocols/message";

export async function callGPT(messages: ChatMessage[]) {
  const res = await fetch("/api/chat", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      model: "gpt-4",
      messages: messages
    })
  });
  const data = await res.json();
  return data.choices[0].message as ChatMessage;
}

contexts/ChatContext.tsx (Context 관리)

import { createContext, useContext, useState } from "react";
import { ChatMessage } from "../protocols/message";
import { callGPT } from "../models/gpt";

const ChatContext = createContext(null);

export const ChatProvider = ({ children }) => {
  const [messages, setMessages] = useState<ChatMessage[]>([]);

  const sendMessage = async (content: string) => {
    const userMessage: ChatMessage = { role: "user", content };
    const newMessages = [...messages, userMessage];
    setMessages(newMessages);

    const assistantMessage = await callGPT(newMessages);
    setMessages([...newMessages, assistantMessage]);
  };

  return (
    <ChatContext.Provider value={{ messages, sendMessage }}>
      {children}
    </ChatContext.Provider>
  );
};

export const useChat = () => useContext(ChatContext);
profile
프론트엔드에 백엔드 한 스푼 🥄

0개의 댓글