내 프로덕션 AI 에이전트를 망가뜨린 날짜 형식 (그리고 지루한 해결책)
요약
프로덕션 환경에서 AI 에이전트가 잘못된 날짜 형식을 처리하며 발생한 데이터 오염 사례와 그 해결책을 다룹니다. 에이전트 자체의 수정 대신 입력과 출력 단계에 검증기(Validator)를 도입하여 시스템의 신뢰성을 확보하는 방법을 제시합니다.
핵심 포인트
- 테스트 케이스 통과가 프로덕션의 안정성을 보장하지 않음
- 에이전트는 모호한 입력을 잘못된 값으로 확신하며 처리할 수 있음
- 입력과 출력 단계에 스키마 검증기를 도입하여 데이터 오염 방지
- AI 출력의 신뢰성은 모델이 아닌 래퍼 로직(Wrapper logic)에서 결정됨
데모는 깔끔했습니다. 43개의 테스트 케이스가 모두 통과되었습니다. 에이전트는 구조화된 입력 (structured input)을 받아 처리하고, 그 결과를 다운스트림 (downstream)에 작성했습니다. 스테이징 (staging) 환경에서 수십 번 실행되는 것을 지켜보았고, 모든 것이 정상적이었습니다.
실제 서비스에 배포했습니다. 3일 후, 데이터베이스에서 1970년 날짜가 기록된 데이터들을 발견했습니다.
데모가 숨겼던 것
테스트 입력값들은 날짜 필드가 일관된 형식으로 구성되어 있었습니다. ISO 8601, 깔끔한 문자열, 특이사항 없음. 하지만 프로덕션 (production) 환경에서는 하나의 업스트림 (upstream) 시스템이 다른 형식의 날짜를 보냈습니다. 에이전트는 해당 필드를 읽고, 그것이 무엇을 의미하는지 그럴듯하게 추측하여 결과를 작성했습니다. 예외 (exception)도, 경고 (warning)도 없었습니다. 그저 잘못된 날짜가, 아무도 지켜보지 않는 새벽 3시에, 확신에 차서 다운스트림에 작성되었을 뿐입니다.
실패 모드 (failure mode)는 극적이지 않았습니다. 에이전트는 사람들이 상상하는 방식처럼 환각 (hallucinate)을 일으키지 않았습니다. 모호한 입력을 모호하지 않은 것으로 취급했고, 가장 가능성 높은 해석을 선택했으며, 틀렸습니다. 정확히 아무것도 깨지지 않기 때문에 포착하기 어려운, 조용하고 확신에 찬 오류였습니다. 출력값은 멀쩡해 보입니다. 데이터 타입 (data type)도 정확합니다. 단지 값이 1970년일 뿐입니다.
나는 해피 패스 (happy path)를 43번 테스트했습니다. 배드 패스 (bad path)는 3일째에 발생했습니다.
아무도 쓰고 싶어 하지 않는 해결책
나는 입력과 에이전트 사이에 검증기 (validator)를 하나 추가했고, 에이전트의 출력과 쓰기 작업 (write operation) 사이에 또 다른 검증기를 추가했습니다.
첫 번째 검증기는 필수 필드가 존재하는지, 날짜 문자열이 예상된 형식과 일치하는지, 문자열 길이가 범위 내에 있는지 확인합니다. 만약 무엇이라도 실패하면, 해당 항목은 에이전트에 도달하지 않습니다. 대신 검토 큐 (review queue)로 이동합니다. 에이전트 호출도, 쓰기도, 조용한 데이터 오염 (silent corruption)도 발생하지 않습니다.
두 번째 검증기는 에이전트가 출력을 생성한 후에 실행됩니다. 무언가가 다운스트림에 작성되기 전에 스키마 (schema)를 확인합니다. 필수 필드가 존재하는지, 타입이 정확한지, 값이 예상 범위 내에 있는지 확인합니다. 출력이 실패하면 동일한 결과가 나타납니다: 검토 큐로 이동하고, 쓰기는 수행되지 않습니다.
에이전트 자체는 변하지 않았습니다. 모델도 변하지 않았습니다. 해결책은 대부분의 프로덕션 시스템이 전통적인 소프트웨어를 위해 이미 갖추고 있지만, AI 출력물에 대해서는 거의 아무도 추가할 생각을 하지 못하는 래퍼 로직 (wrapper logic)이었습니다.
제가 전체 에이전트 운영을 맡고 있는 Agent Enterprise (aienterprise.dk)에서는 이것이 이제 기본값입니다. 영구적인 시스템 (persistent system)에 기록을 수행하는 모든 에이전트는 두 가지 검사를 모두 거칩니다. 에이전트는 자신의 출력이 기록될 만큼 형식이 잘 갖춰졌는지 여부를 결정할 권한이 없습니다. 검증기 (validator)가 결정합니다.
전체 수정 작업을 작성하는 데는 약 한 시간 정도가 걸렸습니다. 흥미로운 코드는 아닙니다.
신뢰성 (Reliability)이 업무의 전부다
데모는 에이전트가 작업을 수행할 수 있음을 증명했습니다. 제가 준비한 43개의 사례와 같이 깨끗한 입력값에 대해서는 훌륭했습니다.
하지만 프로덕션은 당신이 준비한 43개의 사례를 보내주지 않습니다. 프로덕션은 상류 시스템 (upstream system)이 어떤 스케줄로, 어떤 형식을 통해, 어떤 필드가 누락되거나 잘못된 상태로 보내든 상관없이 그대로 전달합니다. 데모에서 작동하는 에이전트와 잘못된 입력값이 들어온 새벽 3시에 작동하는 에이전트는 같은 것이 아닙니다. 그 둘 사이의 간극은 모델의 문제가 아닙니다. 그것은 엔지니어링 (engineering)의 문제입니다.
해결책은 날짜 필드에 대한 타입 체크 (type check)와 실패 시 무엇을 할지에 대한 결정이었습니다. 실패를 기록하게 두는 대신 큐 (queue)로 라우팅하는 검증기 내의 분기 (branch)였습니다. 그게 전부입니다.
그 이후로 저는 무언가에 기록을 수행하는 모든 에이전트에 동일한 패턴을 추가했습니다. 에이전트에 도달하기 전에 입력을 검증하고, 에이전트를 떠나기 전에 출력을 검증하십시오. 그 사이에서 에이전트가 접하는 모든 것은 에이전트의 영역입니다. 그 경계 밖의 모든 것은 당신의 영역입니다.
데모는 역량 (capability)에 관한 것입니다. 프로덕션은 역량이 당신이 설계하지 않은 사례와 마주했을 때 어떤 일이 벌어지는지에 관한 것입니다. 두 번째 환경에서 중요한 유일한 기능은 신뢰성 (reliability)이며, 이는 데모가 보여주는 것과는 거의 항상 다릅니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기