Agentic AI 시스템은 데이터베이스 설계의 암묵적 가정을 위반한다
Agentic AI systems violate the implicit assumptions of database design
TL;DR Highlight
40년간 유지된 '데이터베이스는 인간이 작성한 결정론적 쿼리만 받는다'는 암묵적 계약을 AI 에이전트가 동시다발적으로 깨뜨리고 있으며, 이에 대응하는 구체적인 방어 패턴을 다룬다.
Who Should Read
AI 에이전트에게 데이터베이스 접근 권한을 부여하거나 고려 중인 백엔드/데이터 엔지니어. 특히 프로덕션 DB와 에이전트를 연결하는 시스템을 설계하는 개발자.
Core Mechanics
- 데이터베이스 아키텍처의 근본에는 '호출자는 인간이 작성한 결정론적 코드를 실행하는 애플리케이션'이라는 암묵적 계약이 존재한다. 쿼리는 개발자가 검토하고, 쓰기는 의도적이며, 문제가 생기면 사람이 알아챈다는 가정이 40년간 유지됐다.
- AI 에이전트는 추론 경로에 따라 동적으로 쿼리를 생성하기 때문에, 이전에 한 번도 실행된 적 없는 5개 테이블 조인 쿼리를 날린 후 결과를 생각하면서 커넥션을 붙들고 있다가 전혀 다른 후속 쿼리를 실행할 수 있다. 기존 인덱스와 커넥션 풀 설정이 전혀 맞지 않게 된다.
- 첫 번째 방어선은 statement timeout을 애플리케이션 레벨이 아닌 DB 롤(role) 레벨에서 설정하는 것이다. `ALTER ROLE agent_worker SET statement_timeout = '5s'`처럼 에이전트 전용 롤에 타임아웃을 강제하면 에이전트의 무한 추론 루프가 DB 리소스를 고갈시키는 걸 막을 수 있다.
- `idle_in_transaction_session_timeout` 설정도 중요하다. 에이전트가 트랜잭션을 열어둔 채로 중간에 추론을 멈추는 상황은 실제로 발생하며, 이 타임아웃 없이는 그 커넥션이 무기한 점유된다.
- 에이전트의 쓰기는 '검토된 의도적 쓰기'가 아니다. 실제 documented 장애 사례로, 에이전트가 레거시 API에서 HTTP 200과 빈 결과를 받았을 때(실제로는 DB 커넥션 풀 고갈로 인한 silent failure), 이를 '정상'으로 해석하고 불완전한 데이터로 500건의 트랜잭션을 승인 처리한 사례가 있다.
- 에이전트가 접근할 수 있는 모든 테이블에는 soft delete를 기본으로 적용해야 한다. `deleted_at`, `deleted_by`(예: 'agent:customer-support-v2'), `delete_reason` 컬럼을 추가하고, 에이전트에게는 `active_orders` 같은 뷰만 노출한다. `deleted_by` 컬럼 덕분에 '2시간 전에 에이전트 X가 삭제한 것 전부 보여줘' 같은 디버깅 쿼리가 가능해진다.
- 금융 기록, 재고 변경, 사용자 상태 변경처럼 중요도가 높은 테이블은 append-only 이벤트 로그 방식으로 설계해야 한다. 에이전트는 UPDATE나 DELETE를 실행하지 않고, 새로운 상태를 INSERT만 한다. 이렇게 하면 어떤 에이전트가 언제 무엇을 했는지 전체 이력이 남는다.
Evidence
- 대부분의 댓글이 글의 전제 자체에 강하게 반발했다. '에이전트에게 프로덕션 DB 직접 쓰기 권한을 주는 건 미친 짓'이라는 의견이 압도적이었으며, '저장 프로시저와 API 레이어가 존재하는 이유가 바로 이것'이라는 반론이 많았다. '인턴한테 프로덕션에서 라이브 마이그레이션 시키는 것과 같다'는 비유도 나왔다.
- 실용적인 대안 패턴을 공유한 댓글도 있었다. 읽기는 OLTP가 아닌 OLAP(분석용 DB)로 near real-time 복제 후 처리하고, 쓰기는 직접 DB 접근이 아닌 API 레이어를 통해서만 허용하되, `ban_user(id)` 대신 `request_to_ban_user(id)` 같은 승인 레이어를 두는 패턴을 실제 업무에 적용 중이라고 했다.
- read-only 접근에 대해서는 긍정적인 실사용 경험이 있었다. 프로덕션 DB에 read-only로 LLM 에이전트를 연결했더니 리포트를 직접 만들기 귀찮아하던 임원들이 에이전트에게 분석을 요청하는 방식으로 활용해 생산성이 크게 올랐다는 경험이 공유됐다.
- HTTP 200에 에러 본문을 담아 반환하는 silent failure 패턴에 대한 비판이 나왔다. 이런 API 설계가 에이전트뿐 아니라 기존 시스템에서도 문제를 일으키며, 내부 지표를 좋게 보이려는 팀의 관행에서 비롯된 나쁜 설계라는 지적이었다.
- Databricks가 정확히 이 문제를 위해 Lakebase를 출시했다는 정보가 댓글에 추가됐다. Lakebase는 브랜칭(branching)을 지원해 각 에이전트가 프로덕션 데이터에 영향 없이 독립적인 브랜치에서 쿼리, 스키마 변경, 쓰기 작업을 수행할 수 있다고 한다.
How to Apply
- 에이전트가 DB에 접근해야 하는 상황이라면, 프로덕션 OLTP DB 대신 near real-time 복제본 OLAP DB를 read-only로 연결하라. 쓰기가 필요한 경우에는 DB 직접 접근 대신 `request_to_ban_user(id)` 같은 승인 대기 방식의 API 엔드포인트를 별도로 만들어 에이전트가 그것만 호출하도록 제한하면, 에이전트의 실수가 자동으로 차단된다.
- 에이전트 전용 DB 롤을 만들고 `ALTER ROLE agent_worker SET statement_timeout = '5s'`와 `idle_in_transaction_session_timeout = '10s'`를 롤 레벨에서 강제 설정하라. 이렇게 하면 에이전트의 무한 추론 루프나 커넥션 점유로 인한 DB 리소스 고갈을 애플리케이션 코드 수정 없이 막을 수 있다.
- 에이전트가 쓰기 접근하는 테이블이 있다면, `deleted_at TIMESTAMPTZ`, `deleted_by TEXT`, `delete_reason TEXT` 컬럼을 추가해 soft delete를 적용하고 에이전트에게는 `WHERE deleted_at IS NULL` 조건이 걸린 뷰만 노출하라. 나중에 'agent:support-v2가 오늘 삭제한 레코드 전부'를 조회해 복구하는 것이 가능해진다.
- 금융 거래나 재고처럼 되돌리기 어려운 데이터를 에이전트가 다뤄야 한다면, append-only 이벤트 로그 테이블을 별도로 설계하고 에이전트는 INSERT만 허용하라. UPDATE/DELETE 권한을 DB 레벨에서 아예 박탈하면 에이전트가 실수로 데이터를 덮어쓰거나 삭제하는 사고가 구조적으로 불가능해진다.
Code Example
snippet
-- 에이전트 전용 롤 생성 및 타임아웃 설정
CREATE ROLE agent_worker;
ALTER ROLE agent_worker SET statement_timeout = '5s';
ALTER ROLE agent_worker SET idle_in_transaction_session_timeout = '10s';
-- Soft delete 컬럼 추가
ALTER TABLE orders ADD COLUMN deleted_at TIMESTAMPTZ;
ALTER TABLE orders ADD COLUMN deleted_by TEXT; -- 예: 'agent:customer-support-v2', 'user:abc123'
ALTER TABLE orders ADD COLUMN delete_reason TEXT;
-- 에이전트에게는 이 뷰만 노출 (삭제된 행 자동 필터링)
CREATE VIEW active_orders AS
SELECT * FROM orders WHERE deleted_at IS NULL;Terminology
OLTPOnline Transaction Processing의 약자. 주문 생성, 결제 처리처럼 일상적인 운영 트랜잭션을 처리하는 프로덕션 데이터베이스 유형.
OLAPOnline Analytical Processing의 약자. 대규모 데이터를 집계하고 분석하는 데 최적화된 데이터 웨어하우스 형태의 DB. 복잡한 쿼리를 OLTP보다 훨씬 빠르게 처리한다.
soft delete레코드를 실제로 삭제하지 않고 `deleted_at` 같은 컬럼에 삭제 시각을 기록해 '삭제된 척'하는 패턴. 나중에 복구하거나 감사(audit)가 가능하다.
append-only기존 레코드를 UPDATE/DELETE하지 않고 새로운 상태를 INSERT만으로 추가하는 테이블 설계 방식. 전체 변경 이력이 자동으로 보존된다.
statement_timeoutDB가 단일 쿼리를 실행할 수 있는 최대 시간 제한. 이 시간을 초과하면 DB가 강제로 쿼리를 종료해 리소스 고갈을 방지한다.
idle_in_transaction_session_timeout트랜잭션을 열어둔 채로 아무것도 하지 않는 상태(idle)가 허용되는 최대 시간. 에이전트가 추론 중에 트랜잭션을 무기한 점유하는 것을 막는다.