본문으로 건너뛰기

© 2026 Molayo

Zenn헤드라인2026. 06. 15. 05:58

AI 에이전트의 폭주를 막기 위한 가드레일을 어떻게 구축했는가

요약

실제 운영 환경에서 AI 에이전트가 개인정보를 유출한 사례를 바탕으로, 에이전트의 안전성을 확보하기 위한 가드레일 구축 방법을 설명합니다. 프레임워크가 제공하지 않는 입력/출력 검증, 비용 제어, 도구 호출 유효성 검사의 필요성을 강조합니다.

핵심 포인트

  • 에이전트 워크플로우 단계가 늘어날수록 실패 확률은 기하급수적으로 증가함
  • 가드레일은 정확도를 높이는 것이 아니라 피해 범위(Blast radius)를 제한하는 역할임
  • 입력 가드레일: 프롬프트 인젝션 차단 및 PII 비식별화
  • 출력 가드레일: 환각 및 민감 정보 유출 검증
  • 비용 서킷 브레이커: API 과금 폭주 방지
  • 도구 호출 유효성 검사기: 허가된 도구 및 스키마 준수 확인

운영 3일 차, 나의 에이전트는 한 고객의 이메일 주소를 다른 고객과의 대화에 유출했습니다. 이것은 컨퍼런스 강연에서나 나올 법한 가상 시나리오가 아닙니다. 실제 운영 환경(Production)에서 작동하던 나의 코드가, 테스트해 본 적 없는 행동을 했다는 이야기입니다.

나는 LangGraph와 GPT-4o를 사용하여 서포트 에이전트를 구축했습니다. 지식 베이스(Knowledge base)를 검색하고, 계정 정보를 불러오며, 답장 초안을 작성할 수 있는 기능입니다. 스테이징(Staging) 환경에서는 훌륭하게 작동했습니다. 하지만 운영 환경에서는 정확히 72시간 만에, 특정 사용자의 PII(개인정보)를 다른 사용자의 대화에 노출시켰습니다. 원인은 민망할 정도로 단순했습니다. 모델이 데이터베이스의 가공되지 않은 컨텍스트(Raw context)를 그대로 답장에 포함해 버렸고, 나의 파이프라인에는 이를 체크할 수 있는 장치가 아무것도 없었기 때문입니다.

나중에 보니 해결 방법은 명백했습니다. AI 에이전트 프레임워크가 제공하는 것은 오케스트레이션(Orchestration), 도구 호출(Tool calling), 메모리(Memory)입니다. 안전성(Safety)은 제공해주지 않습니다. 그 부분은 본인의 담당입니다.

왜 당신의 에이전트 프레임워크에는 가드레일이 들어있지 않은가

LangChain, CrewAI, LangGraph, OpenAI의 Agents SDK. 무엇을 선택해도 상관없습니다. 입력 유효성 검사(Input validation), 출력 필터링(Output filtering), 비용 제어(Cost control)를 처음부터 갖추고 있는 것은 단 하나도 없습니다. 그것들은 스스로 추가해야 하는 것이라는 전제하에 만들어졌습니다.

그리고 대부분의 팀은 결국 추가하지 않습니다.

왜 이것이 치명적인지는 간단한 산수로 설명할 수 있습니다. 1단계당 정확도가 90%라고 가정하면, 5단계의 에이전트 워크플로우(Workflow)가 성공할 확률은 59%입니다. 10단계라면 35%까지 떨어집니다. 20단계에서는 12%가 됩니다. 가드레일이 없는 각 단계는 실패율의 곱셈입니다.

가드레일은 정확도를 고쳐주지는 않습니다. 정확도가 무너졌을 때 피해 범위(Blast radius)를 봉쇄하는 것입니다. "에이전트가 틀린 답을 내놓았다"와 "에이전트가 누군가의 사회보장번호를 포함한 틀린 답을 내놓았다"의 차이는 출력 유효성 검사기(Output validator) 하나 차이입니다.

그 후 2주 동안, 나는 가드레일 스택을 계속해서 만들었습니다. 아래의 코드가 최종적으로 도달한 결과물입니다.

모든 에이전트에게 필요한 4가지 가드레일

모든 에이전트에는 4가지 포인트에서의 보호가 필요합니다.

입력 가드레일 (Input Guardrail): LLM이 프롬프트를 보기 전에 프롬프트 인젝션(Prompt injection) 공격을 포착하고, 민감한 데이터를 스크러빙(Scrubbing)한다.

출력 가드레일 (Output Guardrail): 사용자가 보기 전에 응답을 검증하여, 환각(Hallucination)이나 유출된 컨텍스트를 차단한다.

비용 서킷 브레이커 (Cost Circuit Breaker): 루프에 빠지거나 예상치 못하게 긴 대화로 인해 API 과금이 폭주하는 것을 방지한다.

도구 호출 유효성 검사기 (Tool Calling Validator): 에이전트가 허가된 도구만을 스키마 체크(Schema check)를 통과하는 파라미터로 호출하는지 확인한다.

4가지 모두 Python 200행 미만으로 구현할 수 있습니다. 레이턴시(Latency) 비용은 층당 10~50ms입니다. 대안은 장애를 고객으로부터 직접 듣는 것입니다.

입력 가드레일: 위험한 프롬프트를 실행 전에 차단하기

입력 유효성 검사기는 LLM이 프롬프트를 보기 전에 실행됩니다. 하는 일은 두 가지, 인젝션 시도를 차단하고 PII를 비식별화(Redact)하는 것입니다.

import re
from dataclasses import dataclass
@dataclass
...

이것이 철벽은 아닙니다. 진지한 공격자라면 정규 표현식(Regular expression) 기반의 인젝션 탐지는 회피할 수 있습니다. 하지만 흔히 발생하는 시도는 포착할 수 있습니다. 제 경험상, 그것이 실제 인젝션 공격의 약 80%를 차지합니다. 민감한 데이터를 다루는 운영 시스템에서는 정규 표현식 경로 위에 분류기 모델(Lakera Guard나 파인튜닝(Fine-tuned)된 DistilBERT 등)을 한 층 더 얹으십시오.

PII 스크러빙이야말로 3일 차의 나를 구해주었어야 할 부분이었습니다. 만약 입력 가드레일이 그 이메일 주소를 데이터베이스 컨텍스트에서 대화로 들어가기 전에 제거했더라면, 그 유출 사고는 일어나지 않았을 것입니다.

출력 가드레일: 환각을 사용자가 보기 전에 차단하기

출력 유효성 검사는 대부분의 팀이 가드레일을 통째로 건너뛰는 부분입니다. 모델이 답을 냈고, 그럴싸해 보인다면 배포해도 된다고 생각합니다. 하지만 "그럴싸해 보인다"는 신뢰할 수 있는 기준이 아닙니다.

from pydantic import BaseModel, field_validator
from typing import Optional
import json
...

Pydantic 모델은 두 가지 역할을 수행합니다. 구조를 강제하고(LLM은 answer, confidence, sources를 포함하는 JSON을 반환해야 함), 동시에 콘텐츠 체크를 실행합니다(출력에 PII(개인 식별 정보)를 포함하지 않도록 함). 검증(Validation)이 실패하면, 제 에이전트는 추가적인 컨텍스트와 함께 재시도(Retry)를 수행합니다. "당신의 이전 응답은 [이유]로 인해 거부되었습니다. 다시 시도해 주세요"라고 말이죠.

점점 더 구체화되는 지시사항을 포함한 2번의 재시도로 대부분의 검증 실패는 해결됩니다. 3번 실패하면 정형화된 폴백(Fallback) 응답을 반환하고, 인시던트(Incident)로 로그에 기록합니다.

킬 스위치(Kill Switch): 비용과 토큰 예산의 서킷 브레이커(Circuit Breaker)

이것은 아무도 쓰지 않는 가드레일이며, 저에게 400달러를 지불하게 만든 가드레일입니다.

에이전트가 재시도 루프(Retry loop)에 빠지는 버그가 있었습니다. 도구 호출(Tool call)이 실패하면 에이전트가 재시도하고, 재시도가 약간 다른 형태로 실패하면 다시 재시도하는 식이었죠. 각 재시도는 추론 단계에서 토큰을 소모하고, 도구 호출 또한 소모합니다. 제가 알아차리기 전까지, 그것은 밤새 6시간 동안 계속 작동했습니다.

import time
from threading import Lock
class CostCircuitBreaker:
...

요청당(per-request) 상한선은 가장 명확한 케이스를 포착합니다. 예산을 한꺼번에 태워버리는 단일 거대 컨텍스트 윈도우(Context window) 말이죠. 세션(Session) 상한선은 하나의 대화에 대한 총 지출액에 캡(Cap)을 씌웁니다. 속도(Rate) 상한선은 재시도의 폭풍을 방지합니다. 그리고 일일 지출 상한선이 여러분의 절대적인 천장입니다.

저는 일일 상한선을 50달러로 설정했습니다. 그 수치에 도달하면 시스템은 API 호출을 중단하고 "서비스 일시 중지 중"이라는 응답을 반환합니다. 갑작스러운 청구서보다는 다운타임(Downtime)이 차라리 낫습니다.

도구 호출 검증(Tool Call Validation): 에이전트는 승인되지 않은 도구를 호출해서는 안 된다

에이전트가 데이터베이스, 파일 시스템, 외부 API에 접근할 수 있을 때, 도구 호출 검증은 선택 사항이 아닙니다. 이것이 없다면, 탈옥(Jailbreak)되었거나 혼란에 빠진 에이전트가 파괴적인 작업을 수행할 수 있습니다.

class ToolCallGuardrail:
def __init__(self, allowed_tools: dict[str, dict]):
"""
...

저는 기본 거부(Default deny) 방식을 택했습니다. 도구가 허용 목록(Allowlist)에 없다면 에이전트는 그것을 호출할 수 없습니다. 파라미터가 해당 도구의 허용 목록에 없다면 호출은 거부됩니다. 이는 탈옥 시도(모델이 execute_sql이나 delete_record를 호출하려고 하는 경우)와 환각(Hallucination)으로 인해 나타난 도구 이름(생각보다 빈번하게 발생합니다) 모두를 포착합니다.

호출 빈도 상한은 도구마다 별도로 관리합니다. 도구마다 리스크 프로필(Risk profile)이 다르기 때문입니다. 검색 작업은 저렴하고 안전하므로 20번 호출해도 문제가 없습니다. 계정 업데이트는 한 대화에서 많아야 1~2회로 제한해야 합니다.

종합 구성: 프로덕션 가드레일 스택

이 네 가지 요소가 실제 에이전트 파이프라인에서 어떻게 연결되는지 보여줍니다:

User Input
|
[Input Guardrail] --> reject / sanitize
...

각 가드레일은 자신의 판단을 로그에 기록합니다. 거부될 때마다 이유, 원인이 된 입력, 타임스탬프를 포함하는 구조화된 로그(Structured log) 엔트리가 남습니다. 저는 일주일에 한 번 이 로그들에 쿼리를 던져 패턴을 찾습니다. 동일한 인젝션(Injection) 시도가 50번 나타난다면, 그것은 아마도 자동화된 공격일 것입니다. 출력 가드레일이 낮은 신뢰도를 이유로 응답의 15%를 거부하고 있다면, 그것은 상류(Upstream)의 검색(Retrieval) 품질 문제이므로 그 부분을 수정해야 합니다.

네 가지 가드레일 전체의 총 레이턴시 오버헤드(Latency overhead)는 40ms 미만입니다(ML 기반 분류기를 제외하면). 사용자에게는 보이지 않습니다.

처음부터 다시 시작한다면, 무엇을 바꿀 것인가

만약 처음부터 다시 시작한다면, 에이전트의 로직을 단 한 줄이라도 쓰기 전에 가드레일 (Guardrails)을 추가할 것입니다. 여기서 제시한 골격은 Python으로 약 200줄 정도입니다. 2주가 걸린 이유는 기존 시스템에 사후적으로 추가하면서 동시에 PII (개인정보) 인시던트 조사를 병행했기 때문일 뿐입니다.

제 예측으로는, 12개월 이내에 주요 에이전트 프레임워크 (Agent Framework)들이 가드레일을 일급 기능으로 제공하게 될 것입니다. LangGraph는 interrupt 메커니즘을 통해 이미 그 방향으로 움직이고 있습니다. 그때까지는 직접 구현하는 수밖에 없습니다.

입력 가드레일 (Input Guardrails)과 비용 서킷 브레이커 (Cost Circuit Breaker)부터 시작하세요. 이 두 가지만 있었어도 제가 겪은 두 가지 인시던트(PII 유출과 하룻밤 사이의 $400 청구)를 모두 방지할 수 있었을 것입니다. 출력 검증 (Output Validation)은 신뢰도 임계값 (Confidence Threshold)을 튜닝하기 위한 실제 운영 트래픽이 확보된 후에 추가하세요. 도구 호출 검증 (Tool Call Validation)은 에이전트가 무언가에 쓰기 권한을 가지고 있다면 추가하십시오.

가드레일은 에이전트를 똑똑하게 만들지는 않습니다. 하지만 어리석은 순간이 인시던트로 변하는 것을 막아줍니다.

여담: 비용 관리에 대하여

이 글의 서킷 브레이커 섹션(하룻밤 사이의 $400 청구)에서도 언급했듯이, 에이전트를 운영 환경에서 돌리다 보면 은근히 신경 쓰이는 것이 LLM API 비용과 프로바이더 (Provider) 관리입니다. 저 자신은 여러 모델의 전환이나 결제 통합을 위해 EvoLink와 같은 게이트웨이 (Gateway)를 사용하고 있습니다. Claude / GPT / 기타 모델들을 하나의 API로 통합하여 다룰 수 있으면, 위에서 언급한 비용 상한 관리도 한곳으로 집중되어 운영이 수월해집니다. 가드레일과 함께 운영의 안정성을 위한 방안으로 검토해 보셔도 좋을 것 같습니다.

번역 기사입니다. 원문(영어)의 저자: <原著者名>. 출처: https://hackernoon.com/how-i-built-guardrails-that-stopped-my-ai-agent-from-going-rogue

Discussion

AI 자동 생성 콘텐츠

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

원문 바로가기
0

댓글

0