๐Ÿ—„๏ธ PostgreSQL์šฉ MCP ์„œ๋ฒ„ ๊ตฌ์ถ•: Claude ๋ฐ ๋ชจ๋“  AI ํด๋ผ์ด์–ธํŠธ๋กœ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ฟผ๋ฆฌํ•˜๊ธฐ ์ฆ๊ฒ๊ฒŒ ๋นŒ๋“œํ•˜์„ธ์š”

๋ฐœํ–‰: (2025๋…„ 12์›” 3์ผ ์˜คํ›„ 01:37 GMT+9)
7 min read
์›๋ฌธ: Dev.to

Source: Dev.to

์†Œ๊ฐœ

Model Context Protocol (MCP)๋Š” AI ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๋ฐ์ดํ„ฐ ์†Œ์Šค์™€ ์ƒํ˜ธ ์ž‘์šฉํ•˜๋Š” ๋ฐฉ์‹์„ ํ˜์‹ ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋‚ ์”จ ์„œ๋ฒ„์™€ ๊ธฐ๋ณธ ์˜ˆ์ œ๋Š” ์ข‹์€ ์‹œ์ž‘์ ์ด์ง€๋งŒ, ๋Œ€๋ถ€๋ถ„์˜ ์‹ค์ œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ ‘๊ทผ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ฐ€์ด๋“œ์—์„œ๋Š” Claude, VSโ€ฏCode ๋ฐ ๋ชจ๋“  MCP ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์•ˆ์ „ํ•˜๊ณ  ํšจ์œจ์ ์œผ๋กœ ์ฟผ๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ํ”„๋กœ๋•์…˜ ์ˆ˜์ค€์˜ PostgreSQL MCP ์„œ๋ฒ„๋ฅผ ๊ตฌ์ถ•ํ•ฉ๋‹ˆ๋‹ค.

๋๊นŒ์ง€ ์ง„ํ–‰ํ•˜๋ฉด ๋‹ค์Œ์„ ๊ฐ–๊ฒŒ ๋ฉ๋‹ˆ๋‹ค:

  • ์™„์ „ํ•œ ๊ธฐ๋Šฅ์„ ๊ฐ–์ถ˜ PostgreSQL MCP ์„œ๋ฒ„
  • SELECT ์ฟผ๋ฆฌ, ์ง‘๊ณ„ ๋ฐ ๋ฐ์ดํ„ฐ ๊ฒ€์ƒ‰ ์˜ˆ์‹œ
  • ํ”„๋กœ๋•์…˜์— ๋ฐฐํฌํ•  ์ˆ˜ ์žˆ๋Š” ๊ณต๊ฐœ ์ €์žฅ์†Œ
  • Claude Desktop ๋ฐ ๊ธฐํƒ€ MCP ํด๋ผ์ด์–ธํŠธ์™€์˜ ํ†ตํ•ฉ

์ด๊ฒƒ์ด ํ•ด๊ฒฐํ•˜๋Š” ๋ฌธ์ œ๋Š” ๋ฌด์—‡์ธ๊ฐ€์š”?

Claude์—๊ฒŒ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ฌผ์–ด๋ณธ๋‹ค๊ณ  ์ƒ์ƒํ•ด ๋ณด์„ธ์š”:

โ€œ์ด๋ฒˆ ๋ถ„๊ธฐ ๋งค์ถœ ๊ธฐ์ค€ ์ƒ์œ„ 10๋ช…์˜ ๊ณ ๊ฐ์€ ๋ˆ„๊ตฌ์ธ๊ฐ€์š”?โ€

๋˜๋Š”:

โ€œ์ง€๋‚œ 7์ผ ๋™์•ˆ ์‹ฌ๊ฐ๋„โ€ฏโ€˜criticalโ€™์ธ ๋ชจ๋“  ์ธ์‹œ๋˜ํŠธ๋ฅผ ๋ณด์—ฌ ์ฃผ์„ธ์š”.โ€

PostgreSQL MCP ์„œ๋ฒ„๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด Claude๋Š”:

  • ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ง์ ‘ ์—ฐ๊ฒฐ
  • ์•ˆ์ „ํ•˜๊ณ  ์‚ฌ์ „ ์ •์˜๋œ ์ฟผ๋ฆฌ ์‹คํ–‰
  • ๊ตฌ์กฐํ™”๋œ ๋ฐ์ดํ„ฐ ๋ฐ˜ํ™˜
  • ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋ถ„์„ํ•˜๊ณ  ์กฐ์น˜๋ฅผ ์ทจํ•˜๋„๋ก ๋„์›€

์ด๋Š” ๋‹ค์Œ์— ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค:

  • AI ๊ธฐ๋ฐ˜ BI ๋Œ€์‹œ๋ณด๋“œ
  • ์ธ์‹œ๋˜ํŠธ ๊ด€๋ฆฌ ์ž๋™ํ™”
  • ๊ณ ๊ฐ ๋ฐ์ดํ„ฐ ๋ถ„์„
  • ์‹ค์‹œ๊ฐ„ ๋ณด๊ณ  ๋ฐ ์ธ์‚ฌ์ดํŠธ

์•„ํ‚คํ…์ฒ˜ ๊ฐœ์š”

Our MCP Server acts as a bridge between MCP clients (Claude, VSโ€ฏCode) and PostgreSQL:

MCP Client (Claude)
       |
    MCP Protocol
       |
    MCP Server (TypeScript)
       |
  pg (PostgreSQL Driver)
       |
  PostgreSQL Database

์‚ฌ์ „ ์š”๊ตฌ ์‚ฌํ•ญ

  • Node.jsโ€ฏ18 ์ด์ƒ
  • TypeScript ์ง€์‹
  • PostgreSQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค
  • ๊ธฐ๋ณธ MCP ์ดํ•ด

๋‹จ๊ณ„ 1: ํ”„๋กœ์ ํŠธ ์„ค์ •

Create the project:

mkdir mcp-postgres-server
cd mcp-postgres-server
npm init -y
npm install @modelcontextprotocol/sdk pg dotenv
npm install -D typescript @types/node @types/pg

Create tsconfig.json:

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "ES2022",
    "moduleResolution": "node",
    "outDir": "./dist",
    "rootDir": "./src",
    "strict": true,
    "esModuleInterop": true
  }
}

๋‹จ๊ณ„ 2: ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์„œ๋น„์Šค

Create src/database.ts:

import { Pool } from 'pg';
import dotenv from 'dotenv';

dotenv.config();

const pool = new Pool({
  connectionString: process.env.DATABASE_URL,
});

export class DatabaseService {
  async queryUsers(): Promise {
    const result = await pool.query(
      'SELECT id, name, email FROM users LIMIT 10'
    );
    return result.rows;
  }

  async queryIncidents(status: string): Promise {
    const result = await pool.query(
      'SELECT id, title, status, severity FROM incidents WHERE status = $1 ORDER BY created_at DESC',
      [status]
    );
    return result.rows;
  }

  async getStats(): Promise {
    const result = await pool.query(`
      SELECT 
        COUNT(*) as total_incidents,
        SUM(CASE WHEN severity = 'critical' THEN 1 ELSE 0 END) as critical_count,
        SUM(CASE WHEN status = 'open' THEN 1 ELSE 0 END) as open_count
      FROM incidents
    `);
    return result.rows[0];
  }
}

๋‹จ๊ณ„ 3: MCP ์„œ๋ฒ„ ๊ตฌํ˜„

Create src/server.ts:

import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
import { DatabaseService } from './database.js';

const server = new Server({
  name: 'postgres-mcp-server',
  version: '1.0.0',
});

const db = new DatabaseService();

server.setRequestHandler(ListToolsRequestSchema, async () => ({
  tools: [
    {
      name: 'get_users',
      description: 'Retrieve recent users from the database',
      inputSchema: {
        type: 'object',
        properties: {},
        required: [],
      },
    },
    {
      name: 'get_open_incidents',
      description: 'Get all open incidents sorted by date',
      inputSchema: {
        type: 'object',
        properties: {},
        required: [],
      },
    },
    {
      name: 'get_database_stats',
      description: 'Get incident statistics (total, critical, open)',
      inputSchema: {
        type: 'object',
        properties: {},
        required: [],
      },
    },
  ],
}));

server.setRequestHandler(CallToolRequestSchema, async (request) => {
  const { name } = request.params;

  try {
    if (name === 'get_users') {
      const users = await db.queryUsers();
      return {
        content: [{ type: 'text', text: JSON.stringify(users, null, 2) }],
      };
    }

    if (name === 'get_open_incidents') {
      const incidents = await db.queryIncidents('open');
      return {
        content: [{ type: 'text', text: JSON.stringify(incidents, null, 2) }],
      };
    }

    if (name === 'get_database_stats') {
      const stats = await db.getStats();
      return {
        content: [{ type: 'text', text: JSON.stringify(stats, null, 2) }],
      };
    }

    return {
      content: [{ type: 'text', text: `Unknown tool: ${name}` }],
      isError: true,
    };
  } catch (error) {
    return {
      content: [
        {
          type: 'text',
          text: `Error: ${error instanceof Error ? error.message : String(error)}`,
        },
      ],
      isError: true,
    };
  }
});

async function main() {
  const transport = new StdioServerTransport();
  await server.connect(transport);
  console.error('PostgreSQL MCP Server running on stdio');
}

main().catch(console.error);

๋‹จ๊ณ„ 4: ์„ค์ •

Create .env:

DATABASE_URL=postgresql://user:password@localhost:5432/mydb

Update package.json scripts:

{
  "scripts": {
    "build": "tsc",
    "start": "node dist/server.js",
    "dev": "tsc && npm start"
  },
  "type": "module"
}

๋‹จ๊ณ„ 5: ๋กœ์ปฌ์—์„œ ์‹คํ–‰

npm run build
npm start

๋‹จ๊ณ„ 6: Claude Desktop ์—ฐ๊ฒฐ

Edit your Claude Desktop config file:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows: %APPDATA%\\Claude\\claude_desktop_config.json
{
  "mcpServers": {
    "postgres": {
      "command": "node",
      "args": ["/absolute/path/to/dist/server.js"],
      "env": {
        "DATABASE_URL": "postgresql://user:password@localhost:5432/mydb"
      }
    }
  }
}

Claude Desktop์„ ์žฌ์‹œ์ž‘ํ•˜์„ธ์š”. ์ด์ œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์•„์ด์ฝ˜์ด ํ‘œ์‹œ๋˜๊ณ  ์ด ๋„๊ตฌ๋“ค์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค!

ํ”„๋กœ๋•์…˜์„ ์œ„ํ•œ ๋ชจ๋ฒ” ์‚ฌ๋ก€

  • ์—ฐ๊ฒฐ ํ’€๋ง: pg Pool ์‚ฌ์šฉ (์ด๋ฏธ ์ฝ”๋“œ์— ํฌํ•จ๋จ)
  • ํŒŒ๋ผ๋ฏธํ„ฐํ™”๋œ ์ฟผ๋ฆฌ: ํ•ญ์ƒ $1, $2 ์ž๋ฆฌํ‘œ์‹œ์ž ์‚ฌ์šฉ
  • ์˜ค๋ฅ˜ ์ฒ˜๋ฆฌ: ์˜๋ฏธ ์žˆ๋Š” ์˜ค๋ฅ˜๋ฅผ ํฌ์ฐฉํ•˜๊ณ  ๋ฐ˜ํ™˜
  • ๊ฒ€์ฆ: ์ฟผ๋ฆฌ ์ „์— ๋„๊ตฌ ์ž…๋ ฅ ๊ฒ€์ฆ
  • ๋ชจ๋‹ˆํ„ฐ๋ง: ๋ชจ๋“  ์ฟผ๋ฆฌ์™€ ์‘๋‹ต ์‹œ๊ฐ„์„ ๊ธฐ๋ก
  • ์†๋„ ์ œํ•œ: ๋Œ€๋Ÿ‰ ์š”์ฒญ์— ๋Œ€ํ•œ ๋ฐฑํ”„๋ ˆ์…” ๊ตฌํ˜„

๊ณต๊ฐœ ์ €์žฅ์†Œ

์ „์ฒด ์†Œ์Šค ์ฝ”๋“œ๋Š” ๋‹ค์Œ์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
GitHub Repository: mcpโ€‘postgresโ€‘server

์ €์žฅ์†Œ์—๋Š” ๋‹ค์Œ์ด ํฌํ•จ๋ฉ๋‹ˆ๋‹ค:

  • ์ „์ฒด TypeScript ๊ตฌํ˜„
  • Docker ์ง€์›
  • ๋ฐฐํฌ ์Šคํฌ๋ฆฝํŠธ
  • ์˜ˆ์‹œ ์Šคํ‚ค๋งˆ
  • ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ

๋ฐฐํฌ ์˜ต์…˜

Google Cloud Run

gcloud run deploy mcp-postgres \
  --source . \
  --set-env-vars DATABASE_URL=your_connection_string

๋กœ์ปฌ Docker

docker build -t mcp-postgres .
docker run -e DATABA
Back to Blog

๊ด€๋ จ ๊ธ€

๋” ๋ณด๊ธฐ ยป

C# ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ Excel์„ PDF๋กœ ๋ณ€ํ™˜

๊ฐœ์š” Excel ํŒŒ์ผ์„ ๊น”๋”ํ•˜๊ณ  ๊ณต์œ  ์ค€๋น„๊ฐ€ ๋œ PDF๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๊ฒƒ์ด ๋А๋ฆฌ๊ฑฐ๋‚˜ ๋ณต์žกํ•œ ๊ณผ์ •์ผ ํ•„์š”๋Š” ์—†์Šต๋‹ˆ๋‹ค. GroupDocs.Conversion Cloud SDK๋ฅผ ์‚ฌ์šฉํ•˜๋ฉดโ€ฆ

์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š” PostgreSQL ๋ฐฑ์—…์„ ์œ„ํ•œ ๊ผญ ์•Œ์•„์•ผ ํ•  pg_dump ์˜ต์…˜ Topโ€ฏ10

PostgreSQL์˜ pg_dump ์œ ํ‹ธ๋ฆฌํ‹ฐ๋Š” ๋…ผ๋ฆฌ ๋ฐฑ์—…์„ ๋งŒ๋“ค๊ธฐ ์œ„ํ•œ ๋Œ€ํ‘œ์ ์ธ ๋„๊ตฌ์ด์ง€๋งŒ, ์ง„์ •ํ•œ ํž˜์€ ์‚ฌ์šฉ์ž ์ •์˜๋ฅผ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•˜๋Š” ์ˆ˜์‹ญ ๊ฐœ์˜ commandโ€‘line ์˜ต์…˜์— ์žˆ์Šต๋‹ˆ๋‹ค.