Day 13/90: AI 도구가 수용할 수 있는 것과 반드시 반환해야 하는 것을 정의하기
요약
본 글은 LLM 기반 AI 도구의 신뢰성을 확보하기 위해 '도구 계약(tool contracts)' 정의가 필수적임을 강조합니다. 입력 인수는 JSON Schema를 통해 속성, 필수 필드 등을 명확히 제한해야 하며, 데이터 타입 변환에 대한 엄격한 유효성 검증 정책이 필요합니다. 또한 MCP는 구조화된 예측 가능한 출력을 보장하여 시스템의 안정성을 높입니다.
핵심 포인트
- 도구 선택, 인수 생성, 작업 실행은 별개의 관심사로 분리해야 합니다.
- JSON Schema를 활용해 입력 인수의 속성 및 필수 필드를 명확히 정의하는 것이 중요합니다.
- 데이터 타입 변환 시에는 엄격한 유효성 검증 정책을 적용하여 오류를 방지해야 합니다.
- MCP는 구조화된 도구 결과를 위한 선택적 outputSchema를 지원하여 예측 가능성을 높입니다.
Day 13/90: AI 도구가 수용할 수 있는 것과 반드시 반환해야 하는 것을 정의하기
LLM은 검색 도구를 선택하고 다음을 전송합니다:
{
"query": "무료 환불 정책은 무엇인가요?",
"limit": "몇 개"
...
}
이 요청은 사람에게는 이해할 수 있습니다. 하지만 백엔드는 여전히 정수(integer)를 필요로 합니다.
“몇 개”가 무엇을 의미하는지 추측해야 할까요? 기본값을 사용해야 할까요? 오류를 반환해야 할까요?
여기서 '도구 계약(tool contracts)'이 유용해집니다. 이 주제를 탐색하면서 저는 function-calling 연구, JSON Schema, 그리고 Model Context Protocol 사양을 살펴보았습니다.
한 가지 실질적인 교훈이 눈에 띄었습니다: 도구를 선택하는 것, 유효한 인수를 생성하는 것, 허용된 작업을 실행하는 것은 별개의 관심사입니다.
function-calling 연구가 알려주는 것
ICML 2025에서 발표된 Berkeley Function Calling Leaderboard (BFCL)는 모델이 다양한 환경에서 올바른 함수 호출을 수행할 수 있는지 평가합니다. 이는 함수 호출을 명시적인 평가가 필요한 기능으로 취급합니다. 유창한 응답만으로는 정확한 도구 사용을 입증하지 못합니다.
저의 엔지니어링 결론은 실제 호출 자체를 평가하는 것입니다: 어떤 도구가 선택되었는지, 어떤 인수가 제공되었는지, 그리고 실행이 의도된 결과를 생성했는지를 확인해야 합니다.
Schema가 그 문제의 일부를 해결하는 데 도움을 줍니다.
1. 도구가 수용할 수 있는 것을 정의하기
문서 검색 도구의 경우, 입력 계약은 다음을 요구할 수 있습니다:
- 최소한 하나의 공백이 아닌 문자를 포함하는 쿼리(query).
- 1에서 10 사이의 정수 결과 제한(integer result limit).
- 예상치 못한 필드가 없어야 함.
JSON Schema는 속성, 필수 필드, 그리고 추가 속성이 허용되는지 여부를 선언하기 위한 키워드를 제공합니다. 속성을 정의한다고 해서 자동으로 필수 항목이 되는 것은 아니며, 이는 별도로 지정해야 합니다.
우리가 제안하는 계약에 따르면:
| 페이로드 | 예상 결과 |
|---|---|
{"query": "환불 정책", "limit": 3} | 수용함 (Accept) |
| ... |
이것들은 측정된 실험 결과가 아닌 예시적인 경우들입니다. 이들은 구현 전에 의도된 동작을 구체화합니다.
2. 변환이 허용되는지 결정하기
더 미묘한 사례가 있습니다:
{
"query": "refund policy",
"limit": "3"
...
여기서 "3"이 숫자 3으로 변환되어야 할까요, 아니면 유효성 검증에 실패해야 할까요?
이는 유효성 검증 정책에 따라 달라집니다.
Pydantic의 문서는 일반적인 강제 변환(coercion) 동작과 엄격 모드(strict mode)를 구분합니다. 엄격 모드는 변환을 제한하고 잘못된 타입을 더 적극적으로 거부합니다. 엄격한 동작은 또한 타입과 유효성 검증이 Python 객체를 받는지 JSON을 받는지 여부에 따라 달라집니다.
이 도구의 정수(integer) 제한의 경우, 저는 해당 문자열을 거부하고 특정 오류를 반환할 것입니다. 핵심은 그 동작 방식을 의도적으로 선택하고 테스트하는 것입니다.
3. 출력에 계약(Contract)을 부여하라
애플리케이션은 실행 후 예측 가능한 결과를 필요로 합니다.
성공적인 검색 결과는 다음과 같을 수 있습니다:
{
"status": "success",
"results": [
...
MCP는 구조화된 도구 결과를 위한 선택적 outputSchema를 지원합니다. 이 스키마가 선언되면, 사양은 서버가 일치하는 구조화된 결과(conforming structured results)를 반환하도록 요구하며 클라이언트에게 이를 검증할 것을 권장합니다.
이를 통해 다운스트림 코드(downstream code)는 작업할 명시적인 구조를 얻게 됩니다.
하지만 이는 검색된 텍스트가 정확하거나 관련성이 있다는 것을 증명하지는 못합니다. 구조적 유효성과 증거의 품질은 별도의 검사가 필요합니다.
4. 빈 결과와 실패를 분리하여 관리하라
저는 이러한 결과를 다르게 표현할 것입니다:
{"status": "success", "results": []}
{
"status": "error",
"error": {
...
첫 번째는 검색이 매치되는 결과 없이 완료되었음을 의미합니다. 두 번째는 검색 자체가 완료될 수 없었음을 의미합니다.
이는 애플리케이션 설계 선택입니다. 이로 인해 다음 단계가 누락된 증거를 보고할지, 재시도할지, 아니면 일시적인 실패를 설명할지 결정하는 데 도움이 됩니다.
5. 권한 검증을 별도로 수행하라
완벽하게 타입이 지정된 요청이라 할지라도 사용자가 접근할 수 없는 문서를 요청할 수 있습니다.
MCP 사양은 입력 유효성 검사(input validation)와 접근 제어(access controls)를 서버의 개별 책임으로 나열합니다. 스키마 유효성 검사를 통과하는 것이 권한을 확립하는 것은 아닙니다.
검색 도구(retrieval tool)의 경우, 따라서 인자 계약(argument contract)과 요청된 데이터에 대한 호출자의 접근 권한을 모두 확인해야 합니다.
제가 얻은 교훈(takeaway): 도구 스키마는 도구에 무엇이 들어오고 나갈 수 있는지를 정의합니다. 런타임 검증(Runtime validation)이 그 계약을 강제합니다. 권한 부여(Authorization) 및 백엔드 확인(backend checks)이 어떤 동작이 허용되는지 결정합니다.
간단한 실험을 위해, 저는 승인된(accepted) 페이로드와 거부된(rejected) 페이로드, 잘못 구성된 출력(malformed outputs), 빈 결과(empty results), 그리고 도구 실패(tool failures)부터 시작하여 각각 관찰된 동작을 기록할 것입니다.
귀하의 AI 애플리케이션에서 더 많은 문제를 일으킨 것은 예상치 못한 도구 인자(unexpected tool arguments)입니까, 아니면 일관성 없는 도구 응답(inconsistent tool responses)입니까?
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기