LLM 함수 호출(Function Calling) 완전 가이드: JSON Schema·툴 사용·에러 복구
LLM 함수 호출(Function Calling) 완전 가이드: JSON Schema·툴 사용·에러 복구
LLM 함수 호출을 올바르게 설계하면 모델이 정확한 구조화 응답을 내고, 외부 API·DB·검색·계산 같은 툴 사용을 안전하게 자동화할 수 있습니다. 이 글은 LLM 함수 호출 핵심 개념부터 JSON Schema 설계, 툴 라우팅, 오류 복구/재시도, 보안·비용·평가까지 실무 관점으로 정리한 LLM 함수 호출 실전 가이드입니다.
LLM 함수 호출을 활용해 구조화 출력(JSON), 안전한 툴 실행, 에러 복구/재시도 전략을 구현하는 방법을 단계별로 설명합니다. JSON Schema 설계 패턴, 파라미터 검증, 라우팅/가드레일, 비용 절감, A/B 평가 지표와 운영 팁까지 포함했습니다.
목차
1. 왜 지금 LLM 함수 호출인가
2. 핵심 개념과 아키텍처
3. JSON Schema 설계 패턴(예제 코드 포함)
4. 툴 라우팅·가드레일·에러 복구
5. 운영: 로그·평가·비용 최적화
1. 왜 지금 LLM 함수 호출인가
핵심 요약: 자유 텍스트에서 구조로, 추측에서 실행으로.
LLM은 자연어 생성에 강하지만, 프로덕션 서비스에선 정해진 포맷(JSON/SQL 등)과 정확한 파라미터가 필요합니다. LLM 함수 호출은 모델이 함수(툴)의 이름과 인자를 제안하고, 애플리케이션이 이를 검증·실행해 결과를 다시 모델에 제공하는 패턴입니다. 이 방식은 (1) 자유 텍스트를 구조화 데이터로 바꾸고, (2) 외부 시스템 호출을 안전하게 통제하며, (3) 가시성 높은 로그를 남겨 디버깅·평가를 쉽게 합니다.
실무에서 LLM 함수 호출은 챗봇, 고객지원, 가격 견적, 데이터 추출, 요약+질의(예: RAG), 워크플로 자동화 등 거의 모든 생성형 AI 제품의 중심 아키텍처로 자리잡고 있습니다.
2. 핵심 개념과 아키텍처
핵심 요약: 모델 ↔ 오케스트레이터 ↔ 툴의 명확한 경계.
- 모델(Model): 사용자 프롬프트와 컨텍스트를 바탕으로 "어떤 함수를 어떤 인자로 호출할지"를 제안합니다.
- 오케스트레이터(애플리케이션): 모델 출력을 구문/스키마 검증한 뒤, 권한/쿼터/레이트리밋을 확인하고 툴을 실행합니다. 결과를 모델에 관찰값(observation)으로 돌려주거나, 곧바로 사용자 응답을 빌드합니다.
- 툴/함수(Function/Tool): 검색, DB 질의, 사내 API, 결제, 이메일/슬랙 전송, 계산기 등 외부 행위를 담당합니다.
기본 흐름(단일 호출)
- 사용자 질문 → 2) 모델: function_call 제안 → 3) 오케스트레이터: 인자 검증/정규화 → 4) 툴 실행 → 5) 결과를 모델에 넣어 최종 답 생성 → 6) 구조화 응답/레포트 반환.
멀티스텝(에이전트) 확장
- 계획(Plan) → 실행(Act) → 관찰(Observe) 루프를 적용합니다. 각 스텝마다 최대 스텝 수, 툴 화이트리스트, 토큰 한도를 제한해 폭주를 방지합니다.
3. JSON Schema 설계 패턴(예제 코드 포함)
핵심 요약: 스키마가 품질을 결정한다. 필수/옵셔널, 열거형, 포맷, 디폴트를 명확히.
3.1 스키마 기본 예제(TypeScript)
// 예: 항공권 검색 함수
export const searchFlightsSchema = {
name: "search_flights",
description: "Search flights by route/date with constraints",
parameters: {
type: "object",
properties: {
origin: { type: "string", minLength: 3, description: "IATA code" },
destination: { type: "string", minLength: 3 },
date: { type: "string", format: "date" },
cabin: { type: "string", enum: ["economy", "business", "first"] },
nonstop: { type: "boolean", default: false },
pax: { type: "integer", minimum: 1, maximum: 9, default: 1 }
},
required: ["origin", "destination", "date"],
additionalProperties: false
}
} as const;
설계 포인트
- enum·format으로 의도 공간을 좁혀 환각을 줄입니다.
- required/additionalProperties:false로 허용 인자만 통과시킵니다.
- 기본값(default)을 지정하면 재질문 횟수를 줄일 수 있습니다.
3.2 파라미터 정규화와 검증(Node.js)
import Ajv from "ajv";
const ajv = new Ajv({ allErrors: true, removeAdditional: "all" });
const validate = ajv.compile(searchFlightsSchema.parameters as any);
function normalizeAndValidate(input: any) {
// 예: IATA 대문자 변환
if (input.origin) input.origin = String(input.origin).toUpperCase();
if (input.destination) input.destination = String(input.destination).toUpperCase();
const ok = validate(input);
if (!ok) throw new Error("schema_validation_error:" + ajv.errorsText(validate.errors));
return input;
}
3.3 구조화 출력 강제(JSON)
모델 최종 응답도 JSON Schema로 강제하면 후처리가 쉽습니다. 예: answer, citations[], confidence 필드 정의. 실패 시 백오프 재시도 또는 포맷 수정 프롬프트를 사용합니다.
4. 툴 라우팅·가드레일·에러 복구
핵심 요약: 화이트리스트, 속성 기반 라우팅, 실패 안전(fail-safe)로 운영 신뢰도 확보.
4.1 툴 라우팅 전략
- 규칙 기반: 인텐트/엔티티·도메인·지역 등 메타데이터로 함수 선택. 예) price > threshold이면 quote_premium 사용.
- 모델 기반: 다수 함수 중 tool selection을 모델이 제안. 오케스트레이터가 최종 필터링.
- 하이브리드: 규칙으로 1차 후보를 고르고, 모델이 점수화하여 선택.
4.2 가드레일(Guardrails)
- 화이트리스트/블랙리스트: 외부 URL·파일 경로·SQL 키워드 제한.
- 쿼터/레이트 리밋: 사용자·조직·툴별 제한으로 남용 방지.
- 샌드박스/프록시: 서버 사이드에서만 툴 호출을 허용하고, 네트워크/파일 IO를 격리.
- 프롬프트 주입 방어: 시스템 프롬프트에 "툴 인자 외 정보는 무시" 규칙을 명시.
4.3 에러 복구·재시도 패턴
- 유효성 실패: 스키마 오류 메시지를 요약해 모델에 피드백 → 재시도.
- 툴 실패: retryable과 non-retryable로 구분. 전자는 지수 백오프와 서킷 브레이커 적용.
- 불완전 인자: 추가 질문(Follow-up)을 트리거하여 결측 값을 확보.
- 타임아웃: 부분 결과를 반환하고, 백그라운드로 보강(예: 가격 비교가 늦을 때).
예시: 재시도 래퍼(Python)
import time, random
def retry(fn, max_attempts=3, backoff=0.8):
for i in range(max_attempts):
try:
return fn()
except RetryableError as e:
if i == max_attempts - 1: raise
time.sleep((backoff ** i) + random.random()/10)
5. 운영: 로그·평가·비용 최적화
핵심 요약: 모든 호출을 이벤트로 기록하고, 품질/비용을 함께 본다.
5.1 관찰 가능성(Observability)
- 이벤트 스키마: session_id, user_id, prompt, tool_name, args, validation_ok, latency_ms, token_in/out, errors[], feedback 등.
- 리플레이/리그레션 테스트: 과거 세션을 재실행해 모델/프롬프트 변경에 따른 영향을 검증.
5.2 평가 지표(Eval)
- 정확도: 구조화 필드 정확률(예: 날짜·IATA 코드), 함수 선택 정확도.
- 결과 품질: 사용자 채택률, 클릭률, Thumb-up/다운, CSAT.
- 성능: 평균 지연, 95/99p, 실패율.
- 비용: 요청당 토큰, 툴 호출당 비용, 캐시 적중률.
5.3 비용 최적화
- 컨텍스트 패킹: 꼭 필요한 메시지만 유지, 이전 호출 결과는 요약 캐시로 대체.
- 함수 디스커버리 제한: 노출 함수 수를 줄이면 모델 토큰과 혼동이 감소.
- 프리/포스트 검증: 불필요한 툴 실행을 미리 차단.
- 결과 캐시: 동일 파라미터 결과를 TTL로 캐싱, 리소스 절약.
결론
핵심 요약: 스키마·가드레일·관찰성 3종 세트를 표준화하라.
LLM 함수 호출은 모델 능력을 비즈니스 실행으로 연결하는 핵심입니다. 성공 조건은 명확합니다. (1) 잘 설계된 JSON Schema, (2) 툴 라우팅과 가드레일, (3) 로그/평가/비용 관리의 표준화입니다.
이 3가지를 팀의 코딩 컨벤션으로 승격하면, 기능 추가와 모델 교체가 빨라지고 장애 대응도 쉬워집니다. 오늘 소개한 패턴을 최소한의 예제로 시작해, 서비스 맥락에 맞춰 점진적으로 고도화해 보세요.