어느 날 갑자기 데이터베이스 서버의 CPU 점유율이 100%를 찍고 연결 요청이 모두 거부되는 상황이 벌어진다. 로그를 살펴보니 사람이 짠 적 없는 복잡한 조인(Join, 여러 테이블의 데이터를 합쳐서 가져오는 작업) 쿼리가 수백 개나 실행되고 있다. 범인은 바로 스스로 판단해 데이터를 찾는 에이전트 AI(Agentic AI, 목표를 달성하기 위해 스스로 계획을 세우고 도구를 사용하는 AI)다.
에이전트 AI가 무너뜨린 세 가지 설계 전제
Postgres(오픈 소스 관계형 데이터베이스)의 쿼리 플래너(Query Planner, 데이터를 가장 효율적으로 찾는 경로를 결정하는 장치)는 그동안 사람이 짠 예측 가능한 패턴에 맞춰 최적화되어 왔다. 하지만 에이전트 AI는 추론 경로에 따라 매번 다른 쿼리를 생성하며, 결과값을 처리하는 동안 연결을 계속 유지한다. 특히 `idle_in_transaction_session_timeout`(트랜잭션 상태에서 아무 작업 없이 대기하는 시간을 제한하는 설정) 값이 제대로 설정되지 않으면, AI가 생각에 잠긴 사이 데이터베이스 연결 슬롯이 모두 차버리는 현상이 발생한다.
자율적 쓰기 작업과 새로운 방어 기제
예전에는 모든 데이터 수정이나 삭제 작업이 개발자의 검토를 거친 코드에 의해 실행되었다. 이제는 에이전트 AI가 스스로 판단해 데이터를 쓰기 때문에, 잘못된 이해로 수천 개의 행을 한꺼번에 수정하거나 네트워크 오류로 같은 작업을 반복해서 수행하는 일이 빈번하다. 이를 막기 위해 데이터를 완전히 지우는 하드 삭제 대신 `deleted_by` 컬럼을 추가해 기록만 남기는 소프트 삭제(Soft Delete, 데이터를 실제로 지우지 않고 삭제 표시만 하는 방식)를 기본으로 채택해야 한다.
더 민감한 금융 기록 같은 경우에는 기존 데이터를 수정하지 않고 새로운 상태만 계속 추가하는 어펜드 온리(Append-only, 추가만 가능한 기록 방식) 테이블 구조를 도입해 모든 변경 이력을 추적하는 이벤트 소싱(Event Sourcing, 상태 변경 이력을 모두 저장해 현재 상태를 재구성하는 방식) 패턴을 적용하는 것이 안전하다.
또한, AI가 같은 작업을 여러 번 시도해도 결과가 한 번만 반영되도록 멱등성 키(Idempotency Key, 동일한 요청이 여러 번 들어와도 결과가 같게 만드는 고유 식별자)를 사용해야 한다. 에이전트는 다음과 같은 방식으로 키를 생성해 요청을 보낸다.
idempotency_key = f"{task_id}_{step_id}"이렇게 하면 데이터베이스는 유니크 제약 조건(Unique Constraint, 중복된 값이 들어오지 못하게 막는 규칙)을 통해 중복 쓰기를 자동으로 차단할 수 있다.
개발자가 체감하는 가장 큰 변화는 연결 풀(Connection Pool, 데이터베이스 연결을 미리 만들어 두고 돌려쓰는 저장소)의 크기 계산법이 완전히 달라졌다는 점이다. 기존에는 동시 요청 수만 고려하면 됐지만, 이제는 쿼리 실행 시간과 LLM(거대언어모델) 추론 시간, 그리고 추론 단계 수를 모두 곱한 시간이 연결 유지 시간으로 잡힌다. 하나의 작업이 여러 개의 서브 에이전트(Sub-agent, 큰 작업을 나누어 수행하는 하위 AI)를 생성해 병렬로 연결을 점유하면서, 개발 환경에서는 멀쩡하던 시스템이 실제 서비스 환경에서 순식간에 연결 부족으로 마비되는 결과로 이어진다.
이제 데이터베이스는 똑똑한 애플리케이션의 보조 도구가 아니라, 제멋대로 행동하는 AI를 제어하는 최후의 안전장치가 되어야 한다.




