Erdmates Logo
Erdmates
블로그 목록으로
AIMCP스키마설계PostgreSQL

AI 에이전트가 읽는 데이터베이스: MCP 시대의 스키마 설계 원칙

AI 에이전트가 MCP로 데이터베이스에 직접 접속하는 일이 늘고 있습니다. 에이전트가 스키마를 잘못 해석하지 않도록 이름·주석·제약 조건을 설계하고, 권한을 안전하게 나누는 방법을 정리합니다.

2026년 10월 12일8 분 읽기

AI 에이전트가 데이터베이스를 직접 읽기 시작했다

MCP(Model Context Protocol)는 AI 도구가 외부 데이터와 시스템에 연결하는 방식을 하나로 맞추려는 오픈 표준입니다. Anthropic이 2024년 11월 25일 공개했고, 2025년 12월 9일 Linux Foundation 산하 Agentic AI Foundation에 기증되었습니다. 데이터베이스용 MCP 서버를 붙이면 AI 에이전트가 테이블 목록과 컬럼을 조회하고 SQL을 직접 실행할 수 있습니다.

여기서 설계 관점의 변화가 생깁니다. 사람 개발자는 사내 위키를 읽거나 동료에게 물어볼 수 있지만, 에이전트가 보는 것은 대부분 데이터베이스 카탈로그 — 테이블 이름, 컬럼 이름과 타입, 제약 조건, 주석 — 입니다. 스키마가 곧 문서가 되어야 에이전트가 엉뚱한 테이블을 조인하거나 단위를 착각하지 않습니다.

이 글은 사람에게도 좋지만 에이전트에게는 더 중요한 다섯 가지 원칙을 PostgreSQL 기준으로 정리합니다.

1. 이름은 줄이지 말고 의미대로

에이전트는 usr_amt_cd 같은 약어를 추측해서 해석합니다. 추측은 틀릴 수 있습니다.

-- 피해야 할 이름: 약어, 단위 없음, 의미 없는 플래그
CREATE TABLE ord (
  id     BIGINT PRIMARY KEY,
  usr    BIGINT,
  amt    NUMERIC,
  flg    CHAR(1),
  dt     TIMESTAMP
);

-- 권장: 의미·단위·시간대가 이름과 타입에 드러난다
CREATE TABLE orders (
  id            BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
  customer_id   BIGINT        NOT NULL,
  amount_krw    NUMERIC(12,0) NOT NULL,
  is_refunded   BOOLEAN       NOT NULL DEFAULT false,
  ordered_at    TIMESTAMPTZ   NOT NULL DEFAULT now()
);
  • 단위와 통화를 이름에: amount_krw, duration_ms, weight_g
  • 불리언은 is_·has_로: flg 대신 is_refunded
  • 같은 개념은 모든 테이블에서 같은 이름으로: 어떤 곳은 user_id, 어떤 곳은 member_no라면 에이전트는 둘이 같은 것인지 알 수 없습니다
  • 시각은 TIMESTAMPTZ로: 시간대가 없는 값은 사람도 에이전트도 해석이 갈립니다

2. COMMENT ON으로 의미를 카탈로그에 남긴다

PostgreSQL의 COMMENT ON은 설명을 카탈로그(pg_description)에 저장합니다. 코드 주석이나 위키와 달리 데이터베이스에 붙어 다니므로, 스키마를 조회하는 도구라면 같은 경로로 함께 읽을 수 있습니다.

COMMENT ON TABLE orders IS '고객 주문. 결제 완료 시점에 생성되며 취소해도 행을 지우지 않는다(is_refunded로 표시).';
COMMENT ON COLUMN orders.amount_krw IS '결제 금액(원, 부가세 포함). 할인 적용 후 금액.';
COMMENT ON COLUMN orders.is_refunded IS '전액 환불 여부. 부분 환불은 refunds 테이블 참조.';

저장된 설명은 이렇게 조회합니다.

SELECT a.attname                                  AS column_name,
       format_type(a.atttypid, a.atttypmod)       AS data_type,
       col_description(a.attrelid, a.attnum)      AS description
FROM pg_attribute a
WHERE a.attrelid = 'orders'::regclass
  AND a.attnum > 0
  AND NOT a.attisdropped;

무엇을 적으면 좋을까요?

  • 값의 단위·포함 범위(부가세 포함 여부, 할인 전후)
  • 상태값의 의미와 전이 규칙
  • 소프트 삭제 여부와 "실제로 유효한 행"의 조건
  • 다른 테이블과의 관계에서 주의할 점(부분 환불은 다른 테이블 등)

3. 규칙은 제약 조건으로 — 에이전트는 애플리케이션 코드를 보지 못한다

"이 컬럼은 pending, paid, shipped 중 하나"라는 규칙이 애플리케이션 코드에만 있으면 에이전트에게는 존재하지 않는 규칙입니다. 제약 조건으로 선언하면 카탈로그에서 읽을 수 있고, 잘못된 값을 쓰려 해도 데이터베이스가 거부하는 마지막 방어선이 됩니다.

CREATE TABLE customers (
  id     BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
  email  TEXT NOT NULL UNIQUE
);

CREATE TABLE shipments (
  id           BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
  order_id     BIGINT NOT NULL REFERENCES orders (id),
  status       TEXT   NOT NULL
               CHECK (status IN ('pending', 'paid', 'shipped', 'delivered')),
  shipped_at   TIMESTAMPTZ,
  CHECK (status <> 'shipped' OR shipped_at IS NOT NULL)
);
  • 외래 키를 명시하면 에이전트가 조인 경로를 추측하지 않고 카탈로그에서 확인할 수 있습니다
  • CHECK는 허용 값과 컬럼 간 규칙을 드러냅니다
  • NOT NULL·UNIQUE는 "항상 있다", "하나뿐이다"라는 사실을 알려 줍니다

4. 에이전트에게 보여줄 면을 뷰로 정리한다

"월 매출"을 에이전트가 매번 원본 테이블에서 계산하게 두면, 질문할 때마다 환불 포함 여부나 시간대 처리가 달라질 수 있습니다. 합의된 정의를 뷰 하나로 고정하고 설명을 붙이면 에이전트는 그 뷰를 쓰면 됩니다.

CREATE VIEW monthly_revenue AS
SELECT date_trunc('month', ordered_at AT TIME ZONE 'Asia/Seoul') AS month_kst,
       sum(amount_krw)                                          AS revenue_krw,
       count(*)                                                 AS order_count
FROM orders
WHERE NOT is_refunded
GROUP BY 1;

COMMENT ON VIEW monthly_revenue IS '월 매출(원). 한국 시간 기준 월, 전액 환불 주문 제외.';

5. 권한은 최소로 — 경계는 GRANT, 나머지는 보조 장치

에이전트용 계정은 별도 역할로 만들고 필요한 스키마의 읽기 권한만 줍니다.

CREATE ROLE ai_reader LOGIN;  -- 비밀번호·인증 방식은 운영 환경 정책에 따라 설정

GRANT USAGE  ON SCHEMA analytics TO ai_reader;
GRANT SELECT ON ALL TABLES IN SCHEMA analytics TO ai_reader;
ALTER DEFAULT PRIVILEGES IN SCHEMA analytics GRANT SELECT ON TABLES TO ai_reader;

-- 실수 방지용 기본값 (보안 경계는 아님)
ALTER ROLE ai_reader SET default_transaction_read_only = on;
ALTER ROLE ai_reader SET statement_timeout = '15s';

주의할 점이 있습니다. default_transaction_read_only와 statement_timeout은 세션에서 사용자가 다시 바꿀 수 있는 설정입니다. 실수로 쓰기 쿼리를 날리거나 무거운 쿼리가 오래 도는 것을 줄여 주지만, 막아 주는 것은 아닙니다. 실제 경계는 GRANT로 준 권한입니다.

  • 개인정보 컬럼은 에이전트용 스키마의 뷰에서 아예 빼는 편이 안전합니다
  • 행 단위로 범위를 나눠야 하면 ALTER TABLE ... ENABLE ROW LEVEL SECURITY와 정책(CREATE POLICY)을 씁니다
  • 운영 원본이 아니라 읽기 복제본에 연결하면 무거운 분석 쿼리가 서비스에 주는 영향을 줄일 수 있습니다

Erdmates로 설계할 때

Erdmates에서 테이블과 컬럼에 설명을 적어 두면, PostgreSQL DDL로 내보낼 때 COMMENT ON TABLE·COMMENT ON COLUMN 문으로 함께 나옵니다(MySQL은 테이블 COMMENT). 반대로 기존 데이터베이스의 SQL을 가져올 때도 COMMENT ON 문을 읽어 ERD의 설명으로 되살립니다. ERD에서 외래 키 관계를 선으로 확인하면서 이름과 설명을 다듬어 두면, 사람과 에이전트가 같은 문서를 보게 됩니다.

마무리

에이전트가 데이터베이스를 직접 다루는 시대의 스키마 설계는 새로운 기술이 아니라 오래된 원칙을 더 엄격하게 지키는 일입니다. 의미가 드러나는 이름, 카탈로그에 남는 설명, 제약 조건으로 선언된 규칙, 합의된 정의를 담은 뷰, 최소 권한. 이 다섯 가지를 갖춘 스키마는 에이전트가 덜 틀리게 만들고, 틀리더라도 데이터베이스가 막아 줍니다.

Erdmates로 바로 시작하세요

AI 기반 ERD 에디터로 데이터베이스 설계를 시작하세요. 무료로 사용할 수 있습니다.

무료 데모 체험무료로 시작하기

관련 기사

bigint, UUID v4, UUID v7: 기본 키 고르는 법 (PostgreSQL 18 uuidv7() 포함)

bigint·UUID v4·UUID v7 기본 키의 장단점을 비교하고, PostgreSQL 18에 들어온 uuidv7()로 달라진 점과 상황별 선택 기준을 정리합니다.

PostgreSQL 19 미리보기: 스키마 설계와 운영에 영향을 주는 변화 (베타 4 기준)

정식 출시를 앞둔 PostgreSQL 19의 변경 사항 가운데 테이블 설계·마이그레이션·운영에 직접 영향을 주는 것을 공식 릴리스 노트(베타 4) 기준으로 정리합니다. 베타에서 되돌려진 기능과 업그레이드 전 확인할 동작 변화도 함께 봅니다.

pgvector로 RAG용 벡터 테이블 설계하기: 차원, 인덱스, 필터링까지

PostgreSQL에서 pgvector로 문서 임베딩을 저장할 때의 테이블 구조, 벡터 타입별 차원 제한, HNSW 인덱스, 메타데이터 필터링 설계를 pgvector 0.8 기준으로 정리합니다.

Erdmates Logo
Erdmates

AI 기반 ERD 협업 에디터로 자연어로 데이터베이스를 설계하고 팀과 실시간으로 협업하세요.

서비스

  • 기능 소개
  • 요금제
  • 데모
  • SQL → ERD 변환

리소스

  • 블로그
  • 도움말
  • 문의하기

법적 고지

  • 이용약관
  • 개인정보처리방침
  • 제3자 제공
상호: Produx|대표: 최정회
주소: 강원특별자치도 원주시 솔우물2길 4-1 (무실동)
이메일: master@erdmates.com
개인정보관리책임자: 최정회|호스팅 서비스 제공자: Amazon Web Services

© 2026 Produx. All rights reserved.