내 프로덕션 에이전트를 망가뜨린 null 입력값과 그 해결책
요약
프로덕션 환경에서 null 입력값으로 인해 발생하는 에이전트의 환각(hallucination) 문제와 그 해결책을 다룹니다. 모델의 재학습 대신 입력 단계에서 결정론적 체크(deterministic check)를 수행하는 가드 로직을 추가하여 시스템의 신뢰성을 확보하는 방법을 제시합니다.
핵심 포인트
- 데모와 프로덕션 환경의 입력 데이터 차이를 인지해야 함
- LLM은 결측치를 그럴듯한 데이터로 채우려는 환각 특성이 있음
- 모델 수정보다 입력 단계의 결정론적 가드 로직이 더 효과적임
- 신뢰할 수 있는 에이전트는 엣지 케이스를 사람에게 라우팅해야 함
데모는 3주 동안 결함 없이 완벽하게 실행되었습니다. 모든 테스트 입력값은 깔끔하게 파싱되었고, 모든 출력값은 올바르게 라우팅되었으며, 저는 우리가 신뢰할 수 있는 시스템을 구축했다고 생각했습니다.
그러던 중, 한 공급업체가 제목(subject line)이 비어 있는 확인 이메일을 보냈습니다.
주문 참조(order references)를 추출하여 큐(queue)로 라우팅하도록 설계된 에이전트는 문자열(string)을 기대한 위치에서 null 값을 받았습니다. 시스템이 충돌(crash)하지는 않았습니다. 차라리 충돌하는 편이 더 나았을 것입니다. 대신 에이전트는 그럴듯해 보이는 주문 참조를 생성했고, 이를 라우팅했으며, 다운스트림(downstream) 시스템은 이를 실제 데이터처럼 처리했습니다. 아무도 4시간 동안 이를 발견하지 못했습니다.
이것이 바로 데모의 문제입니다. 데모는 당신이 예상하는 것과 유사한 입력값을 사용합니다. 하지만 프로덕션(Production)은 그렇지 않습니다.
데모가 숨긴 것
저는 aienterprise.dk에서 에이전트 운영을 구축하고 실행하므로, 스택(stack)의 모든 계층을 제어할 수 있습니다. 이 문제가 발생했을 때, 저는 전체 트레이스(trace)를 확인할 수 있었습니다. 에이전트의 시스템 프롬프트(system prompt)에는 "제목에서 주문 참조를 추출하십시오"라고 적혀 있었습니다. 합리적인 지침입니다. 제목이 존재할 때는 매번 잘 작동합니다.
하지만 제목이 존재하지 않을 때, 프롬프트가 잘 작성된 LLM은 "주문 참조를 찾을 수 없습니다"라고 말하지 않습니다. 대신 그 공백을 채워버립니다. 그럴듯해 보이는 무언가를 지어냅니다. 환각(hallucination)은 무작위적인 노이즈가 아닙니다. 그것은 그럴듯하고 구조화된 노이즈입니다. 바로 그 점이 위험을 초래합니다. 무작위적인 실패는 포착하기 쉽습니다. 하지만 자신감 넘치고 형식이 잘 갖춰진 잘못된 답변은 그렇지 않습니다.
데모에서는 결코 제목이 null인 이메일을 보내지 않았습니다. 그럴 생각을 해본 적도 없었습니다. 입력값이 너무 기본적이라서 이를 엣지 케이스(edge case)로 고려하지 않았습니다. 하지만 프로덕션 환경에서 그것은 엣지 케이스가 아닙니다. 흔히 일어나는 일입니다.
화려하지 않은 해결책
저는 아무것도 재학습(retrain)시키지 않았습니다. 프롬프트를 조정하지도 않았습니다. 모델 호출(model call) 전에 가드(guard)를 추가했습니다.
이제 에이전트가 입력값에 접근하기 전에 결정론적 체크(deterministic check)가 실행됩니다: 제목 필드가 존재하며 비어 있지 않은가? 만약 그렇지 않다면, 해당 메시지는 플래그(flag)와 함께 대기 큐(hold queue)로 라우팅됩니다. 그러면 사람이 이를 검토합니다. 에이전트는 잘못된 형식의 입력값을 절대 보지 못합니다.
그 가드는 단 12줄의 코드입니다. 제가 올해 만든 것 중 가장 흥미롭지 않은 코드입니다. 하지만 동시에 그것이 에이전트를 신뢰할 수 있게 만드는 요소입니다.
이 패턴은 일반화됩니다. 에이전트가 입력값에서 구조를 가정하는 모든 곳은, 결국 프로덕션 (Production) 환경에서 비구조화된 데이터가 전송될 곳입니다. 해결책은 더 똑똑한 모델이 아닙니다. 해결책은 경계 (Boundary)입니다. 즉, 모델이 추측하게 두는 대신 모델 실행 전에 작동하여 잘못된 입력을 사람에게 라우팅 (Routing)하는 체크 로직입니다.
이것이 바로 신뢰성 (Reliability)이 유일한 기능이라고 말하는 이유입니다. 데모는 에이전트가 작업을 수행할 수 있음을 증명합니다. 프로덕션은 아무도 지켜보지 않는 새벽 3시에, 잘못된 입력값이 들어왔을 때도 그 작업을 반복해서 수행함을 증명합니다. 이 둘은 서로 다른 주장입니다. 비용을 지불하는 사람에게 중요한 것은 오직 두 번째 주장뿐입니다.
이제 에이전트는 하루에 약 200건의 라우팅 (Routing) 작업을 사고 없이 처리합니다. 대기 큐 (Hold queue)는 일주일에 약 두 번 정도 사용됩니다. 대기 큐가 사용될 때면, 사람이 도착한 기이한 데이터를 확인하고 처리하며, 저는 실제 프로덕션 환경이 어떤 모습인지에 대해 새로운 것을 배웁니다.
2027년을 위한 참고 사항
만약 여러분이 EU AI Act (EU 인공지능법)에 따라 고위험 카테고리에 속하는 고객을 위해 에이전트를 구축하고 있다면, 준수 마감일은 2027년 12월 2일입니다. 이는 고용 결정, 생체 인식, 국경 통제, 교육 시스템 등을 포함합니다. 그리 멀지 않은 시점입니다.
잘못된 입력값에 대해 자신 있게 라우팅하고 그럴듯한 오답을 내놓는 시스템은 감사를 통과할 수 없습니다. 제가 설명한 가드레일 (Guard)은 단순히 좋은 엔지니어링이 아닙니다. 적용 범위에 속하는 시스템의 경우, 이는 준수를 위한 최소한의 요건입니다. 유럽 위원회 (European Commission)는 이번 달에 제6조 분류 가이드라인 초안을 발표했습니다. 여러분의 시스템이 적용 범위에 포함되는지 확인하지 않았다면, 지금이 바로 확인해야 할 때입니다.
신뢰성은 나중에 추가하는 기능이 아닙니다. 대기 큐 (Hold queue)가 그것을 증명합니다. 환각 (Hallucination)을 일으킨 주문 참조 번호 또한, 더 비싼 대가를 치르는 방식으로 그것을 증명합니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기