Home [AI 기초] MCP(Model Context Protocol): AI에게 '손과 발'을 달아주는 표준 인터페이스 (feat. JDBC)
Post
Cancel

[AI 기초] MCP(Model Context Protocol): AI에게 '손과 발'을 달아주는 표준 인터페이스 (feat. JDBC)

AI는 똑똑하지만, 눈과 귀가 막혀 있어요 👀

“ChatGPT야, 내 컴퓨터에 있는 user.csv 파일 읽어서 분석해줘”

…불가능합니다. 😢

현재의 LLM은 “똑똑하지만 눈과 귀가 막힌 박사님”과 같아요. 아무리 뛰어난 분석 능력이 있어도, 외부 데이터에 접근할 수 없다면 무용지물이죠.

오늘은 이 문제를 해결하는 혁신적인 기술, MCP(Model Context Protocol)에 대해 알아보겠습니다!


1. MCP의 정의와 문제 의식 🎯

현재의 문제: n × m 지옥

AI 애플리케이션마다 각 데이터 소스에 대한 연동 코드를 따로 짜야 해요.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// 현재 상황: 모든 조합을 일일이 구현해야 함

// ChatGPT → Notion 연동
class ChatGPTNotionIntegration {
    void connectToNotion() { /* 커스텀 구현 */ }
}

// ChatGPT → Slack 연동
class ChatGPTSlackIntegration {
    void connectToSlack() { /* 또 다른 커스텀 구현 */ }
}

// Claude → Notion 연동
class ClaudeNotionIntegration {
    void connectToNotion() { /* 또 다시 구현... */ }
}

// Claude → Slack 연동
class ClaudeSlackIntegration {
    void connectToSlack() { /* 또또또... */ }
}

// Gemini → Notion 연동
class GeminiNotionIntegration {
    // 이게 끝이 없어요! 😱
}

문제점:

  • AI 모델 3개 × 데이터 소스 10개 = 30개의 연동 코드 필요
  • 새로운 AI 모델이 나오면? 모든 데이터 소스에 대해 다시 구현
  • 새로운 데이터 소스가 생기면? 모든 AI 모델에 대해 다시 구현

이게 바로 n × m 문제예요!


MCP의 해결책: 표준 인터페이스

MCP(Model Context Protocol)는 Anthropic(Claude 개발사)이 만든 오픈 표준 프로토콜이에요.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// MCP 도입 후: 표준 인터페이스로 통일

// 모든 AI 모델은 MCP Client를 구현
interface MCPClient {
    Response sendRequest(MCPRequest request);
}

// 모든 데이터 소스는 MCP Server를 구현
interface MCPServer {
    Response handleRequest(MCPRequest request);
}

// 이제 조합은 자유!
ChatGPT (MCP Client) ←→ Notion (MCP Server) 
Claude (MCP Client)  ←→ Slack (MCP Server)  
Gemini (MCP Client)  ←→ Postgres (MCP Server) 

// 새로운 AI 모델? MCP Client만 구현하면 모든 서버 사용 가능!
// 새로운 데이터 소스? MCP Server만 구현하면 모든 AI가 사용 가능!

결과:

  • AI 모델 3개 + 데이터 소스 10개 = 13개 구현만 필요 (3 + 10)
  • n × m → n + m (혁명적 감소!)

2. 개발자 비유: JDBC와 USB 🔌

비유 1: JDBC (Java Database Connectivity)

MCP는 AI 세계의 JDBC예요!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// JDBC 없던 시절 (1990년대)
class OracleConnection {
    void connect() { /* Oracle 전용 코드 */ }
    ResultSet query(String sql) { /* Oracle 전용 */ }
}

class MySQLConnection {
    void connect() { /* MySQL 전용 코드 */ }
    ResultSet query(String sql) { /* MySQL 전용 */ }
}

class PostgresConnection {
    void connect() { /* Postgres 전용 코드 */ }
    ResultSet query(String sql) { /* Postgres 전용 */ }
}

// 문제: DB가 바뀌면 모든 코드를 다시 짜야 함!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// JDBC 도입 후 (표준 인터페이스)
public class DatabaseExample {
    
    public static void main(String[] args) {
        // 1. 어떤 DB든 동일한 방식으로 연결
        Connection conn = DriverManager.getConnection(
            "jdbc:mysql://localhost:3306/mydb",  // MySQL
            // "jdbc:oracle:thin:@localhost:1521:orcl",  // Oracle
            // "jdbc:postgresql://localhost/mydb",  // Postgres
            "user", "password"
        );
        
        // 2. 표준 SQL로 동일하게 사용
        Statement stmt = conn.createStatement();
        ResultSet rs = stmt.executeQuery("SELECT * FROM users");
        
        while (rs.next()) {
            System.out.println(rs.getString("name"));
        }
        
        // DB가 바뀌어도 코드는 동일!
    }
}

JDBC의 핵심:

  • 표준 인터페이스 (Connection, Statement, ResultSet)
  • 드라이버 구현 (Oracle, MySQL, Postgres가 각각 구현)
  • 애플리케이션 코드는 변경 없음 (DB 교체 자유)

MCP = AI 세계의 JDBC

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
// MCP 구조 (JDBC와 유사)

// JDBC의 Connection = MCP의 Connection
interface MCPConnection {
    MCPResponse execute(MCPRequest request);
}

// JDBC의 Driver = MCP Server
class NotionMCPServer implements MCPConnection {
    @Override
    public MCPResponse execute(MCPRequest request) {
        // Notion API 호출
        return notionAPI.query(request);
    }
}

class PostgresMCPServer implements MCPConnection {
    @Override
    public MCPResponse execute(MCPRequest request) {
        // Postgres 쿼리 실행
        return jdbcTemplate.query(request.getSql());
    }
}

// 애플리케이션 (AI)는 표준 방식으로 사용
public class ClaudeAI {
    
    public String analyze(String userQuery) {
        // 1. 어떤 데이터 소스든 동일한 방식으로 연결
        MCPConnection conn = MCPClient.connect("mcp://notion");
        // MCPConnection conn = MCPClient.connect("mcp://postgres");
        // MCPConnection conn = MCPClient.connect("mcp://slack");
        
        // 2. 표준 방식으로 데이터 요청
        MCPResponse data = conn.execute(
            new MCPRequest("get_users_data")
        );
        
        // 3. 데이터를 받아서 분석
        return analyzeWithLLM(data);
    }
}

비교표:

구분JDBCMCP
목적데이터베이스 표준화AI 데이터 소스 표준화
표준 인터페이스Connection, StatementMCPConnection, MCPRequest
구현체 (Driver)Oracle, MySQL, PostgresNotion, Slack, Filesystem
사용자Java 애플리케이션AI 모델 (Claude, ChatGPT)
이점DB 교체 용이데이터 소스 교체 용이

비유 2: USB 포트

MCP는 USB 포트와도 같아요!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Before USB (1990년대):
┌──────────┐
│ 컴퓨터    │
└──────────┘
    ││││  ← 각 장치마다 전용 포트
    ││││
    ││││
마우스 키보드 프린터 스캐너
(각각 다른 포트, 다른 드라이버)

After USB (표준화):
┌──────────┐
│ 컴퓨터    │
└──────────┘
    ║ ║ ║  ← USB 포트 (표준)
    ║ ║ ║
마우스 키보드 프린터
(모두 동일한 USB 인터페이스)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Before MCP:
┌───────────┐
│ Claude AI │
└───────────┘
    ││││  ← 각 데이터 소스마다 전용 코드
    ││││
 Notion Slack Postgres GitHub
 (각각 다른 API, 다른 인증)

After MCP:
┌───────────┐
│ Claude AI │
└───────────┘
    ║ ║ ║  ← MCP (표준 프로토콜)
    ║ ║ ║
 Notion Slack Postgres
 (모두 동일한 MCP 인터페이스)

3. MCP Architecture: 3-Tier 구조 🏗️

MCP는 3개의 레이어로 구성돼요.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
/**
 * MCP 3-Tier Architecture
 */

// ┌─────────────────────────────────────┐
// │  1. MCP Host (AI 애플리케이션)       │
// │     예: Cursor, Claude Desktop      │
// └─────────────────────────────────────┘
//              │
//              ↓
// ┌─────────────────────────────────────┐
// │  2. MCP Client (AI 모델)            │
// │     예: Claude, GPT-4               │
// └─────────────────────────────────────┘
//              │
//              ↓ (MCP Protocol)
// ┌─────────────────────────────────────┐
// │  3. MCP Server (데이터 소스)        │
// │     예: Postgres, Notion, Slack     │
// └─────────────────────────────────────┘

public class MCPArchitecture {
    
    // 1. MCP Host: AI 애플리케이션
    public class MCPHost {
        private List<MCPClient> clients = new ArrayList<>();
        
        void initialize() {
            // Cursor, Claude Desktop 등
            clients.add(new ClaudeClient());
        }
    }
    
    // 2. MCP Client: AI 모델
    public class ClaudeClient implements MCPClient {
        
        public String processUserQuery(String query) {
            // 사용자: "내 Postgres의 user 테이블 분석해줘"
            
            // Step 1: 어떤 MCP Server에 접근할지 결정
            MCPServer server = findServer("postgres");
            
            // Step 2: MCP 프로토콜로 요청
            MCPRequest request = new MCPRequest(
                "execute_query",
                Map.of("sql", "SELECT * FROM users")
            );
            
            // Step 3: 서버로부터 데이터 수신
            MCPResponse response = server.handle(request);
            
            // Step 4: LLM으로 분석
            return analyzeWithLLM(response.getData());
        }
    }
    
    // 3. MCP Server: 실제 데이터 소스
    public class PostgresMCPServer implements MCPServer {
        
        @Override
        public MCPResponse handle(MCPRequest request) {
            String action = request.getAction();
            
            if (action.equals("execute_query")) {
                // 실제 Postgres 쿼리 실행
                String sql = request.getParam("sql");
                List<Map<String, Object>> results = jdbcTemplate.queryForList(sql);
                
                return new MCPResponse(results);
            }
            
            throw new UnsupportedOperationException("Unknown action");
        }
        
        @Override
        public List<String> getAvailableActions() {
            return List.of(
                "execute_query",
                "get_schema",
                "list_tables"
            );
        }
    }
}

실제 동작 흐름 (시퀀스 다이어그램)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
사용자: "내 로컬 DB의 user 테이블 조회해줘"

┌─────────┐      ┌──────────┐      ┌─────────┐      ┌──────────┐
│  User   │      │   Host   │      │ Client  │      │  Server  │
│         │      │ (Cursor) │      │(Claude) │      │(Postgres)│
└────┬────┘      └────┬─────┘      └────┬────┘      └────┬─────┘
     │                │                  │                │
     │ "DB 조회해줘"  │                  │                │
     │───────────────>│                  │                │
     │                │  processQuery()  │                │
     │                │─────────────────>│                │
     │                │                  │ MCP Request    │
     │                │                  │ "execute_query"│
     │                │                  │───────────────>│
     │                │                  │                │
     │                │                  │  SQL Execute   │
     │                │                  │  [DB Query]    │
     │                │                  │                │
     │                │                  │ MCP Response   │
     │                │                  │ [User Data]    │
     │                │                  │<───────────────│
     │                │                  │                │
     │                │  LLM Analysis    │                │
     │                │  [분석 결과]      │                │
     │                │<─────────────────│                │
     │                │                  │                │
     │  "총 10명의... "│                 │                │
     │<───────────────│                  │                │
     │                │                  │                │

구체적인 예시: Cursor + Postgres

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
// 실전 예시: Cursor에서 로컬 Postgres DB 조회

public class CursorWithMCP {
    
    public static void main(String[] args) {
        // 1. MCP Host (Cursor) 시작
        MCPHost cursor = new CursorApp();
        
        // 2. Postgres MCP Server 등록
        cursor.registerServer(
            "postgres",
            "mcp://localhost:5432/mydb"
        );
        
        // 3. 사용자 쿼리
        String userQuery = "내 DB의 user 테이블에서 가장 많이 주문한 사람 찾아줘";
        
        // 4. Claude (MCP Client)가 처리
        ClaudeClient claude = cursor.getClient();
        
        // 4-1. Claude가 필요한 데이터 파악
        String analysis = claude.analyze(userQuery);
        // → "user 테이블과 order 테이블을 JOIN해야겠군"
        
        // 4-2. MCP로 Postgres 서버에 요청
        MCPRequest request = new MCPRequest(
            "execute_query",
            Map.of("sql", """
                SELECT u.name, COUNT(o.id) as order_count
                FROM users u
                JOIN orders o ON u.id = o.user_id
                GROUP BY u.id
                ORDER BY order_count DESC
                LIMIT 1
            """)
        );
        
        MCPResponse response = cursor.sendToServer("postgres", request);
        
        // 4-3. 결과 분석
        String result = claude.generateResponse(response.getData());
        
        System.out.println(result);
        // → "김개발님이 총 25번의 주문으로 가장 많이 주문하셨습니다."
    }
}

핵심 포인트:

  • 더 이상 데이터를 복붙할 필요 없어요! 🎉
  • AI가 직접 로컬 DB에 접근해서 쿼리하고 분석해요
  • 보안: MCP Server는 로컬에서 실행되므로 데이터가 외부로 나가지 않아요

4. MCP의 핵심 컴포넌트 📦

Component 1: Resources (리소스)

“AI가 읽을 수 있는 데이터”

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// Resources = 읽기 전용 데이터
public class MCPResources {
    
    @Resource(name = "file://spec.md")
    public String getSpecFile() {
        return Files.readString(Path.of("spec.md"));
    }
    
    @Resource(name = "db://users")
    public List<User> getUsers() {
        return userRepository.findAll();
    }
    
    @Resource(name = "notion://project-docs")
    public String getNotionDocs() {
        return notionAPI.getPageContent("project-docs");
    }
}

// AI가 사용할 때
ClaudeAI claude = new ClaudeAI();
String spec = claude.readResource("file://spec.md");
claude.analyze("이 스펙에 맞춰 코드 생성해줘");

Component 2: Tools (도구)

“AI가 실행할 수 있는 함수”

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// Tools = AI가 호출 가능한 함수
public class MCPTools {
    
    @Tool(name = "execute_sql")
    public List<Map<String, Object>> executeSql(
        @Param("query") String sql
    ) {
        return jdbcTemplate.queryForList(sql);
    }
    
    @Tool(name = "send_slack_message")
    public void sendSlackMessage(
        @Param("channel") String channel,
        @Param("message") String message
    ) {
        slackAPI.postMessage(channel, message);
    }
    
    @Tool(name = "create_jira_ticket")
    public String createJiraTicket(
        @Param("title") String title,
        @Param("description") String description
    ) {
        return jiraAPI.createIssue(title, description);
    }
}

// AI가 사용할 때
사용자: "DB 조회해서 결과를 Slack에 공유해줘"

Claude:
1. executeSql("SELECT * FROM users WHERE active = true")
2. [결과 분석]
3. sendSlackMessage("#general", "현재 활성 사용자는 총 50명입니다")

Component 3: Prompts (프롬프트 템플릿)

“재사용 가능한 프롬프트”

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// Prompts = 프롬프트 템플릿
public class MCPPrompts {
    
    @Prompt(name = "analyze_code")
    public String getCodeAnalysisPrompt(
        @Param("code") String code
    ) {
        return """
            다음 코드를 분석해주세요:
            
            ```
            %s
            ```
            
            다음 항목을 체크해주세요:
            1. 버그나 잠재적 문제
            2. 성능 개선 포인트
            3. 보안 취약점
            4. 리팩토링 제안
        """.formatted(code);
    }
    
    @Prompt(name = "generate_test")
    public String getTestGenerationPrompt(
        @Param("method") String methodSignature
    ) {
        return """
            다음 메서드의 JUnit 테스트를 작성해주세요:
            
            %s
            
            요구사항:
            - 정상 케이스, 예외 케이스 모두 포함
            - Given-When-Then 패턴 사용
            - AssertJ 사용
        """.formatted(methodSignature);
    }
}

5. 실전 활용 사례 💡

Use Case 1: 로컬 개발 환경 분석

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// Before MCP: 데이터 복붙의 지옥
개발자: [application.yml 복사]
       [Controller.java 복사]
       [Service.java 복사]
       "ChatGPT야, 이 코드 분석해줘"
       
ChatGPT: "파일이 너무 많네요. 나눠서 보내주세요"
개발자: [ 복사...]

// After MCP: AI가 직접 접근
개발자: "내 프로젝트의 모든 Controller 분석해서 REST API 문서 만들어줘"

Cursor (MCP):
1. Filesystem MCP Server로 프로젝트 파일 스캔
2. 모든 @RestController 파일 자동 수집
3. Claude가 분석  Swagger 문서 생성
4. 결과를 로컬 파일로 저장

 5 작업이 30초로! 🚀

Use Case 2: 데이터베이스 리팩토링

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// Scenario: 레거시 DB 스키마 분석

개발자: "Postgres의 모든 테이블 스키마 분석하고, 
       정규화가 안 된 테이블 찾아서 개선안 제시해줘"

MCP 동작:
┌──────────────┐
 Claude       
└──────┬───────┘
       
       ├─> Postgres MCP Server: "SHOW TABLES"
       ├─> Postgres MCP Server: "DESCRIBE users"
       ├─> Postgres MCP Server: "DESCRIBE orders"
       ├─> ... (모든 테이블 자동 조회)
       
       └─> [분석 결과]
           "users 테이블의 address 컬럼이 비정규화되어 있습니다.
            다음과 같이 개선하시길 권장합니다:
            
            1. addresses 테이블 분리
            2. user_id를 FK로 연결
            3. 마이그레이션 스크립트:
               [자동 생성된 SQL]
           "

 수동 분석 2시간  자동 분석 2!

Use Case 3: 팀 협업 자동화

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// Scenario: Git Commit 분석 후 Slack 공유

개발자: "오늘 커밋된 내용 분석해서 팀 채널에 요약 공유해줘"

MCP 동작:
1. Git MCP Server: 오늘 커밋 목록 조회
2. Filesystem MCP Server: 변경된 파일 읽기
3. Claude: 변경사항 분석
4. Slack MCP Server: 메시지 전송

Slack 메시지:
"[오늘의 커밋 요약 🎉]
- UserService에 이메일 인증 기능 추가
- Order API에 취소 기능 구현
- 총 15개 파일 수정, 300줄 추가

주요 변경사항:
1. 이메일 인증 플로우 개선
2. 주문 취소 시 재고 복구 로직 추가
3. 테스트 커버리지 85% → 92%"

 매일 반복 작업이 자동화!

6. MCP vs Function Calling 비교 🔄

“그럼 OpenAI의 Function Calling과 뭐가 다른가요?”

구분Function CallingMCP
범위특정 API 호출프로토콜 표준
표준화OpenAI 전용모든 AI 모델 가능
데이터 접근제한적 (API 통해서만)직접 접근 가능
실행 위치원격 (OpenAI 서버)로컬 (내 컴퓨터)
보안데이터가 외부로데이터가 로컬에만
확장성함수 단위서버 단위
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// Function Calling (OpenAI)
@FunctionCall
public String getWeather(String city) {
    // 1. OpenAI 서버에서 실행
    // 2. 특정 API만 호출 가능
    // 3. 데이터가 OpenAI 서버로 전송됨
    return weatherAPI.get(city);
}

// MCP
@MCPServer
public class WeatherMCPServer {
    
    @Tool
    public String getWeather(String city) {
        // 1. 내 로컬에서 실행
        // 2. 어떤 API든 호출 가능
        // 3. 데이터가 로컬에만 존재
        return weatherAPI.get(city);
    }
    
    @Resource
    public String getHistoricalData() {
        // 로컬 DB, 파일 시스템 등 자유롭게 접근
        return database.query("SELECT * FROM weather_history");
    }
}

핵심 차이:

  • Function Calling: “특정 기능을 원격으로 호출”
  • MCP: “표준 프로토콜로 로컬 데이터에 접근”

7. MCP 시작하기 🚀

Step 1: MCP Server 찾기

1
2
3
4
5
6
7
8
9
10
11
# 공식 MCP Servers (Anthropic 제공)
- @modelcontextprotocol/server-filesystem  # 로컬 파일
- @modelcontextprotocol/server-postgres    # Postgres
- @modelcontextprotocol/server-github      # GitHub
- @modelcontextprotocol/server-slack       # Slack
- @modelcontextprotocol/server-google-drive # Google Drive

# 커뮤니티 MCP Servers
- mcp-server-notion     # Notion
- mcp-server-jira       # Jira
- mcp-server-docker     # Docker

Step 2: Claude Desktop 설정

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// ~/Library/Application Support/Claude/claude_desktop_config.json

{
  "mcpServers": {
    "postgres": {
      "command": "npx",
      "args": [
        "-y",
        "@modelcontextprotocol/server-postgres",
        "postgresql://localhost/mydb"
      ]
    },
    "filesystem": {
      "command": "npx",
      "args": [
        "-y",
        "@modelcontextprotocol/server-filesystem",
        "/Users/me/projects"
      ]
    }
  }
}

Step 3: 사용하기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Claude Desktop 실행 후:

사용자: "내 프로젝트 폴더의 모든 Java 파일 개수를 세어줘"

Claude: 
[Filesystem MCP Server 사용]
"총 47개의 Java 파일이 있습니다.
- Controller: 8개
- Service: 12개
- Repository: 6개
- Entity: 15개
- DTO: 6개"

사용자: "Postgres의 users 테이블에 몇 명이나 있어?"

Claude:
[Postgres MCP Server 사용]
"users 테이블에 총 1,234명의 사용자가 있습니다.
- 활성 사용자: 980명
- 비활성 사용자: 254명"

Step 4: 커스텀 MCP Server 만들기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// 나만의 MCP Server 구현 (Java)

@MCPServer(name = "my-api")
public class MyApiMCPServer {
    
    @Resource(uri = "api://users")
    public List<User> getUsers() {
        return userService.findAll();
    }
    
    @Tool(name = "create_user")
    public User createUser(
        @Param("name") String name,
        @Param("email") String email
    ) {
        return userService.create(name, email);
    }
    
    @Prompt(name = "analyze_users")
    public String getAnalysisPrompt() {
        return """
            다음 사용자 데이터를 분석해주세요:
            - 연령대별 분포
            - 가입 트렌드
            - 활성도 분석
        """;
    }
    
    public static void main(String[] args) {
        // MCP Server 시작
        MCPServerBuilder.create()
            .withServer(new MyApiMCPServer())
            .withPort(3000)
            .start();
    }
}

8. MCP의 미래와 한계 🔮

MCP의 가능성

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 상상해보세요...

개발자: "내 로컬 DB 스키마를 분석하고,
       GitHub의 코드와 비교해서,
       Notion에 정리하고,
       팀 Slack에 공유해줘"

AI (MCP 활용):
1. Postgres MCP Server  스키마 조회
2. GitHub MCP Server  코드 분석
3. Notion MCP Server  문서 작성
4. Slack MCP Server  메시지 전송

 5 안에 완료! 🎉

// 더 나아가...
개발자: "어제부터 오늘까지 변경된 코드를 분석하고,
       영향받는 테이블을 찾아서,
       마이그레이션 스크립트를 생성하고,
       Jira에 배포 티켓을 만들어줘"

 완전 자동화된 개발 워크플로우!

현재의 한계

1. 보안 문제

1
2
3
4
5
6
7
8
9
10
11
12
13
// 문제: AI가 모든 권한을 가지면 위험
AI: "users 테이블의 모든 데이터 삭제"
// → 실제로 삭제됨! 😱

// 해결책: 권한 제한
@MCPServer(permissions = {
    Permission.READ,  // 읽기만 허용
    // Permission.WRITE,  // 쓰기는 금지
    // Permission.DELETE  // 삭제는 금지
})
public class SafeMCPServer {
    // 안전하게 읽기만 가능
}

2. 성능 문제

1
2
3
4
5
6
7
8
9
10
11
12
// 문제: AI가 비효율적 쿼리 생성
AI: 
for (User user : users) {
    query("SELECT * FROM orders WHERE user_id = " + user.getId());
}
// → N+1 문제 발생!

// 해결책: 쿼리 최적화 가이드 제공
@Tool(description = """
    대량 데이터 조회 시 반드시 JOIN 사용하세요.
    N+1 문제를 피하기 위해 한 번에 조회하세요.
""")

3. 표준화 미완성

  • 아직 초기 단계 (2024년 11월 발표)
  • 모든 AI 모델이 지원하는 건 아님
  • 커뮤니티 생태계 발전 중

9. 마치며: 데이터 복붙의 시대는 끝났어요 📋 → 🚫

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
/**
 * 개발자의 진화
 */
public class DeveloperEvolution {
    
    // 2020년: 수동 복붙
    void before() {
        String data = readFile("data.json");  // 파일 열기
        // [Ctrl+C, Ctrl+V]
        askChatGPT("이 데이터 분석해줘: " + data);  // 붙여넣기
    }
    
    // 2023년: Function Calling
    void functionCalling() {
        String data = callAPI("/api/data");  // API 호출
        askChatGPT("분석해줘");  // AI가 API 호출
    }
    
    // 2024년: MCP
    void withMCP() {
        // AI가 직접 접근!
        askClaude("내 로컬 data.json 분석해줘");
        // → Claude가 MCP로 파일 직접 읽음
    }
    
    // 2025년: 완전 자동화
    void future() {
        askClaude("""
            1. 로컬 DB 조회
            2. GitHub 이슈 분석
            3. Notion에 정리
            4. Slack에 공유
            5. Jira 티켓 생성
            
            위 작업을 자동으로 매일 아침 9시에 실행해줘
        """);
        
        // AI가 모든 걸 자동으로!
    }
}

MCP의 핵심 철학:

  1. “AI에게 손과 발을 달아주자” - 외부 데이터 접근 가능
  2. “표준화로 n×m 문제 해결” - JDBC처럼 표준 인터페이스
  3. “로컬 우선, 보안 우선” - 데이터가 내 컴퓨터에만
  4. “개발자는 오케스트레이터” - AI가 도구를 조율

핵심 정리:

Before MCPAfter MCP
데이터 복붙 지옥AI가 직접 접근
각 서비스마다 코드 작성표준 프로토콜로 통일
n × m 연동 코드n + m 구현만 필요
데이터가 외부로 전송로컬에서 안전하게
수동 작업 반복완전 자동화 가능

JDBC가 데이터베이스 세계를 표준화했듯이, MCP는 AI 세계를 표준화하고 있어요!

이제는 “AI야, 이 데이터 복붙할게”가 아니라, “AI야, 내 로컬에서 직접 가져가서 분석해줘”라고 말할 수 있는 시대가 왔습니다! 🚀


참고 자료

  • MCP 공식 문서: https://modelcontextprotocol.io/
  • Anthropic MCP 발표: https://www.anthropic.com/news/model-context-protocol
  • MCP Servers 저장소: https://github.com/modelcontextprotocol/servers
  • MCP Specification: https://spec.modelcontextprotocol.io/
This post is licensed under CC BY 4.0 by the author.

[AI 기초] SDD(Spec-Driven Development): AI 시대, 코딩보다 스펙 작성이 중요한 이유

[AI 실전] MCP 실습 가이드: AI에게 내 로컬 DB(SQLite) 조회 권한 주기