본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 06. 21. 17:09

내가 SchemaBrain을 만든 이유

요약

AI 에이전트가 데이터베이스에 직접 접근할 때 발생하는 보안 및 컨텍스트 문제를 해결하기 위한 SchemaBrain 프로젝트를 소개합니다. 의도를 안전한 SQL로 컴파일하고 PII를 차단하며, 스키마 너머의 비즈니스 로직을 에이전트에게 전달하는 경계 계층을 구축합니다.

핵심 포인트

  • AI 에이전트의 직접적인 SQL 접근에 따른 보안 위험 방지
  • PII(개인정보) 및 자격 증명 유출을 차단하는 방화벽 기능
  • 스키마 정보만으로는 부족한 비즈니스 로직의 컨텍스트 보완
  • 데이터 엔지니어링 관점에서의 안전한 에이전트 데이터 접근 설계

AI 에이전트에게 운영 중인 Postgres에 대한 가공되지 않은 SQL 접근 권한을 주고 싶지 않았습니다. 그래서 저는 다른 경계(boundary)를 구축했습니다. 의도(intent)를 안전한 SQL로 컴파일하고, 쿼리가 실행되기 전에 개인정보(PII)를 거부하며, 변조 방지 가능한 감사(audit)를 유지하는 경계 말입니다.

SchemaBrain's firewall showcase running in the terminal: five get_metric calls — one computed, two refused, two recovered — then the audit chain verifies

단 하나의 명령 — API 키도, Docker도, Postgres도 필요 없습니다. 방화벽이 안전한 지표(metric)를 계산하고, 두 가지 유출(PII + 자격 증명)을 거부하며, 답변할 수 없는 두 가지는 복구한 다음, 감사 체인(audit chain)을 검증합니다. 에이전트는 SQL을 작성한 적이 없습니다.

저는 Postgres, RDS, Oracle, dbt와 같은 데이터 엔지니어로서 경력을 쌓아왔습니다. 그 과정의 대부분은 조용하고 화려하지 않은 진실로 향했습니다. 그것은 바로 스키마(schema)가 결코 전체 이야기를 담고 있지 않다는 것입니다. 컬럼 이름은 거짓말을 합니다. 이를 설명하는 비즈니스 로직(business logic)은 누군가의 머릿속에 있거나, 2년 동안 아무도 업데이트하지 않은 Confluence 페이지에 있거나, Teams 또는 Slack 스레드에 존재합니다. status 컬럼에 7개의 값이 있다면, 그중 당신이 추측할 수 있는 의미를 가진 것은 단 3개뿐일 수도 있습니다. 저는 이를 한두 번이 아니라 직접 목격해 왔습니다.

이 직업이 가르쳐 주는 것은 다음과 같습니다. 무엇이든 데이터가 될 수 있지만, 실제로 유용한 것은 큐레이션(curated)된 부분, 즉 무언가 실질적인 것을 추론할 수 있는 부분입니다. 가공되지 않은 테이블을 신뢰할 수 있는 의미로 바꾸는 것이 데이터 엔지니어링(data engineering) 업무의 전부입니다.

그래서 AI 에이전트들이 데이터베이스 접근 권한을 갖기 시작했을 때, 저는 그들이 인간이 마주하는 것과 똑같은 벽에 부딪히는 것을 지켜보았습니다. 다만 인간보다 더 빠르고, 더 자신 있게 틀릴 뿐이었습니다. 그들은 스키마(schema)는 가지고 있었지만, 의미(meaning)는 가지고 있지 않았습니다.

진짜 문제

유능한 모델을 운영 중인 Postgres 데이터베이스에 연결하면, 거의 즉시 세 가지 문제가 발생합니다.

스키마가 컨텍스트 윈도우 (context window)에 맞지 않으며, 설령 맞는다 해도 도움이 되지 않습니다. 실제 데이터베이스는 수백 개의 테이블과 수천 개의 컬럼으로 구성되어 있습니다. 이 모든 것을 프롬프트 (prompt)에 쏟아붓는다 하더라도, 에이전트 (agent)는 unit_price_cents가 센트 단위의 정수(integer)라는 사실이나, "revenue"가 수금된 인보이스 (invoices)가 아니라 계약된 구독 라인 아이템 (subscription line-items)을 의미한다는 것을 여전히 알지 못합니다. 스키마는 형태 (shape)를 알려줄 뿐, 의미 (meaning)를 알려주지는 않습니다.

모호한 컬럼들. dt_ref, flg_2, amt. 모델은 추측합니다. 때로는 맞게 추측하기도 합니다. 위험한 경우는 모델이 그럴듯하게 추측하고, 당신이 이를 잡아내지 못할 때입니다.

가공되지 않은 SQL (raw SQL)의 진정한 위험성. 이것이 제가 당연해 보이는 방식을 출시하지 못하게 만든 요인이었습니다. 표준적인 패턴 — 에이전트에게 SQL을 실행하는 도구 (tool)를 제공하는 것 — 은 에이전트가 어떠한 SQL이라도 실행할 수 있음을 의미합니다. 혼란에 빠진 에이전트는 4,000만 행 규모의 크로스 조인 (cross join)을 작성합니다. 탈옥 (jailbroken)된 에이전트는 아무도 기억하지 못하는 평문 API 키가 저장되어 있는 users 테이블의 컬럼까지 포함하여 읽어버립니다. 그리고 당신은 감사 로그 (audit log)가 있다면, 그제야 이 사실을 알게 됩니다.

일반적인 해결책은 "읽기 전용 (read-only) 권한을 주고 기도하는 것"입니다. 읽기 전용은 쓰기 작업을 막아줍니다. 하지만 크로스 조인에 대해서는 아무런 조치도 취하지 못하며, 프롬프트의 요청에 따라 에이전트가 데이터베이스의 모든 이메일 주소를 즐겁게 SELECT 하는 상황에 대해서도 아무런 방책이 없습니다.

통찰 (The insight)

해결책은 더 나은 프롬프트나 더 똑똑한 모델이 아닙니다. 그것은 다른 경계 (boundary)를 설정하는 것입니다.

저는 단지 데이터를 이해하게 만들기 위해 에이전트에게 데이터에 대한 완전한 통제권을 주고 싶지 않았습니다. 데이터 이해와 통제는 서로 다른 것이며, 이 둘을 혼동하는 것이 바로 문제의 핵심입니다. 그래서 저는 이것을 "에이전트에게 데이터베이스 접근 권한을 주는 것"으로 생각하기를 멈추고, 에이전트와 Postgres 사이에 위치하는 **신뢰 및 지능 계층 (trust and intelligence layer)**으로 생각하기 시작했습니다. 이 계층은 단 하나의 강력한 원칙을 가집니다. 에이전트는 절대 SQL을 작성하지 않으며, 이 계층은 에이전트가 작성한 SQL을 절대 실행하지 않는다는 것입니다.

Architecture diagram: an MCP client host talks over stdio to the SchemaBrain trust boundary — a 12-tool read-only MCP server plus core (PII firewall, embedder, SHA-256 audit, registry) — which emits read-only SQL to production Postgres

이 계층은 에이전트와 Postgres 사이에 위치합니다. 에이전트는 의도(intent)를 보내고, SchemaBrain은 이를 컴파일하여 자체 측에서 SQL을 실행합니다.

대신, 에이전트는 엔티티(entity), 메트릭(metric), 입도(grain)와 같은 _의도(intent)_를 표현합니다 (예: "플랜 등급별 계약 수익"). SchemaBrain은 해당 의도를 자체 측에서 매개변수화된 SQL (parameterized SQL)로 컴파일하고 실행합니다. 에이전트는 결과 행(rows)을 돌려받고 실행된 정확한 SQL도 전달받지만, 에이전트의 프롬프트에서 데이터베이스의 임의의 문장으로 이어지는 경로는 존재하지 않습니다. 이 보장은 에이전트가 대화로 우회할 수 있는 설정 플래그(config flag)가 아니라 구조적인 것입니다.

이러한 컴파일 단계가 있으면, 경계 지점에 실제 검사(checks)를 배치할 수 있습니다:

  • 쿼리가 실행되기 전에 PII(개인정보)를 거부합니다. 응답에 이미 포함된 후에 거부하는 것이 아닙니다.
  • 조작(fabricate)을 거부합니다. 만약 조인(join)이 존재하지 않는다면 이를 알리고, 에이전트가 파싱해야 하는 문단 대신 복구할 수 있는 기계 판독 가능한(machine-readable) 방식을 전달합니다.
  • 모든 호출을 변조 방지 로그(tamper-evident log)에 기록합니다. 따라서 "에이전트가 실제로 무엇을 했는가"에 대해 암호학적인 답변을 가질 수 있습니다.

SchemaBrain의 실체

SchemaBrain은 AI 에이전트에게 Postgres 데이터베이스에 대한 안전하고 의미론적인(semantic) 접근을 제공하는 오픈 소스 MCP 서버(Apache-2.0)입니다. 이는 로컬 우선(local-first) 방식입니다. 서버는 전적으로 사용자의 기기에서 실행되며, 에이전트의 쿼리는 기기를 절대 벗어나지 않습니다. 외부로 나갈 수 있는 유일한 것은 인덱싱 시점에 수행되는 선택적인 의미론적 강화(semantic-enrichment) 단계뿐입니다. 이는 비용이 제한된 LLM 호출이며, 익명화된 샘플을 사용하도록 사용자가 선택할 수 있습니다. 번들로 제공되는 데모는 이 단계조차 생략합니다. 이러한 절제는 제가 임의로 붙인 마케팅 요소가 아니라, 이 프로젝트의 핵심 목적입니다. 신뢰를 강조하는 제안은 신뢰 계층 자체가 사용자의 스키마(schema)를 몰래 어딘가로 전송하지 않을 때에만 유효하기 때문입니다.

구체적으로는 네 단계로 구성됩니다:

1. 인덱싱(Index). SchemaBrain은 Postgres 스키마를 읽어 로컬 SQLite 저장소에 저장합니다. 테이블, 컬럼, 타입, 선언된 외래 키(foreign keys) 등이 포함됩니다.

2. 시맨틱 강화 (Semantic enrichment). 이것이 지능이 발생하는 지점입니다. 비용이 제한된 LLM 패스 (LLM pass)를 통해 각 컬럼에 대한 평이한 언어 설명을 작성하고, 엔티티 (entities)를 제안하며 (예: users 테이블은 _User_임), 세 가지 소스—선언된 외래 키 (foreign keys), 쿼리 로그 (query log), 그리고 dbt relationships 테스트—로부터 조인 (joins)을 추출합니다. 이는 멀티 홉 BFS (multi-hop BFS)를 사용하여 정준 조인 그래프 (canonical join graph)를 구축하므로, 레이어는 중간 연결 테이블 (junction table)을 거쳐 세 단계를 이동해야 하는 경우에도 _User_에서 _Invoice_로 가는 방법을 알 수 있습니다. 온디바이스 임베딩 (on-device embeddings; BAAI/bge-small, ONNX)이 시맨틱 코사인 검색 (semantic cosine retrieval)을 지원하여, 에이전트가 단순히 이름이 아닌 의미를 통해 적절한 테이블을 찾을 수 있습니다. 사용자는 제안 사항을 명시적으로 검토하고 적용하며, 시맨틱 레이어 (semantic layer)에 자동으로 커밋되는 것은 아무것도 없습니다.

SchemaBrain dashboard showing the join graph — entities as nodes with the multi-hop join paths between them

정준 조인 그래프 (The canonical join graph): 엔티티와 그 사이의 멀티 홉 경로. 이를 통해 레이어는 중간 연결 테이블을 통해서라도 User에서 Invoice로 가는 방법을 알 수 있습니다.

3. MCP 도구 (MCP tools). 서버는 find_relevant_tables, describe_entity, list_metrics, get_metric, resolve_join 등 12개의 읽기 전용 도구를 노출합니다. 이 중 어떤 것도 쓰기 작업을 수행할 수 없습니다. execute()query()는 존재하지 않습니다. 또한 serve는 이중 안전장치로서 데이터베이스 수준에서 default_transaction_read_only=on을 고정하지만, 진정한 보장은 쓰기 도구 자체가 바이너리(binary)에 존재하지 않는다는 점입니다.

4. 방화벽(Firewall) + 모든 호출에 대한 감사(audit). PII 태그는 물리적 컬럼에서 조인(joins)과 지표(metrics)를 거쳐 전파됩니다. 만약 get_metric 호출이 차단된 카테고리를 건드리려고 하면, 컴파일된 SQL은 절대 실행되지 않습니다. 대신 호출 자체가 거부된다는 응답을 받고, 이 거부 기록은 감사 로그(audit log)에 남습니다. 모든 호출, 모든 거부, 모든 복구 시도는 추가 전용(append-only) mcp_audit 테이블에 한 행씩 작성되며, 이는 SHA-256 해시 체인으로 연결되고 브라우저로 검증 가능한 RFC-6962 머클 포함 증명(Merkle inclusion proofs)과 함께 기록됩니다. audit verify는 이 체인을 다시 순회하며, 과거의 어떤 행이라도 재작성된 경우 0이 아닌 값(non-zero)을 반환합니다.

SchemaBrain dashboard audit viewer: an append-only table of every agent call with hash-chain links and Merkle inclusion proofs

추가 전용(append-only) mcp_audit 체인 — 모든 호출, 거부 및 복구 시도는 SHA-256 해시 체인으로 연결되고 브라우저로 검증 가능한 머클 포함 증명과 함께 기록됩니다.

제가 가장 자랑스러운 부분은 바로 그 '거절' 방식입니다. 에이전트가 스키마가 답변할 수 없는 무언가를 요청하는 경우—예를 들어, 사용 이벤트에 plan_id가 없어 플랜 티어별 사용량 볼륨을 요청하는 경우—SchemaBrain은 조인을 환각(hallucinate)하지 않습니다. 대신 구조화된 봉투(structured envelope)를 반환합니다:

{ "kind": "unreachable_entity", "recovery": { "suggested_tool": "resolve_join" } }

거부된 에이전트는 단순히

  • 에이전트가 작성한 SQL을 실행하지 않습니다. 이는 한계가 아니라 설계 의도이며, 이에 대해 사과할 생각은 없습니다. 하지만 사용 사례가 "에이전트가 임의의 분석용 SQL을 작성하게 하는 것"이라면, 현재로서는 이 도구가 적합하지 않습니다. 에이전트가 생성한 SQL을 검사하는 기능은 향후 선택적으로 도입할 수 있는 경로일 뿐, 제품이 피벗(pivot)하려는 방향은 아닙니다.
  • 아직 콘텐츠 인식형 PII (개인정보) 분류를 지원하지 않습니다. 현재의 PII 탐지는 컬럼 이름 패턴 매칭 방식입니다. 12개의 GDPR / CCPA / HIPAA / PCI 카테고리에 걸쳐 60개의 규칙을 사용하며, 사용자의 정책과 관계없이 무조건 거부하는 치명적 유출 방지 하한선(credential, payment_card, government_id)이 설정되어 있습니다. 일반적인 이름의 자유 형식 텍스트(free-text) 컬럼에 숨겨진 PII 값은 이름만으로는 탐지되지 않습니다. 콘텐츠 인식형 분류는 로드맵(roadmap)에 포함되어 있습니다.
  • Postgres 외에는 아무것도 연결할 수 없습니다. 로컬 저장소는 SQLite를 사용하지만, 현재 SQLite, Snowflake, BigQuery 또는 MySQL 소스(source) 커넥터는 없습니다. 이들은 로드맵에 있습니다. 저는 절반만 작동하는 다섯 개의 커넥터보다, 제대로 작동하는 하나의 커넥터를 출시하는 쪽을 택하겠습니다.
  • dbt 임포트는 부분적입니다. dbt 모델을 엔티티(entity)에 바인딩하고, dbt relationships 테스트를 조인(join)에 바인딩합니다. 전체 메트릭/시맨틱 레이어(metric/semantic layer)를 임포트하지는 않습니다. 풍부한 dbt 시맨틱 레이어를 보유하고 있다면, 이 임포트를 마이그레이션(migration)이 아닌 초기 단계의 도움(head start)으로 간주하십시오.
  • 대시보드는 뷰어(viewer)입니다. 선택 사항인 로컬 대시보드는 127.0.0.1에만 바인딩되며, 읽기 전용이고, 설계상 --host 플래그를 지원하지 않습니다. SQL 패드도, 설정도, 쓰기 경로도 없습니다.

수치

비용이 반대 의견의 핵심이기 때문에 저는 비용을 솔직하게 공개합니다. 시맨틱 강화(Semantic enrichment)는 Claude Haiku 4.5에서 실행되며 컬럼당 약 $0.0004가 소요됩니다. 전체 LLM 컬럼 설명을 포함하여 84개 컬럼의 스키마를 인덱싱하는 데는 약 $0.03이 듭니다. Pagila DVD-rental 샘플(87개 컬럼)을 직접 측정한 기준값은 105초에 $0.0299입니다. 변경되지 않은 스키마를 재인덱싱하는 비용은 $0입니다. 콘텐츠 주소 지정 핑거프린팅(content-addressable fingerprinting)이 LLM 호출을 완전히 건너뛰므로, 실제로 변경된 부분에 대해서만 비용을 지불하면 됩니다. 암호 같은 이름의 컬럼은 Haiku로 충분하지 않을 경우 Sonnet 4.6 라우팅을 선택할 수 있습니다.

번들로 제공되는 데모는 API 키 없이도 0달러로 실행할 수 있습니다. 미리 큐레이션된 시맨틱 팩 (semantic pack)이 포함되어 있어, 단 1센트도 쓰기 전에 '거부 후 복구 (refuse-then-recover)' 루프 전체를 관찰할 수 있습니다.

에이전트(Agents)를 실제 Postgres에 연결하는 경우

pip install schemabrain (또는 uvx schemabrain init) 명령어를 사용하면 단 한 번의 명령으로 연결된 MCP 호스트 (MCP host)까지 안내됩니다. 모든 것은 오픈 소스이며, Apache-2.0 라이선스를 따릅니다. 코드는 github.com/Arun-kc/schemabrain에서, 문서는 schemabrain.mintlify.app에서 확인할 수 있습니다.

AI 자동 생성 콘텐츠

본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0