5

JSON Schema: Tool의 청사진

Day 2: Tool 정의 & Function Calling

학습 목표
  • JSON Schema의 핵심 속성을 이해한다
  • 제조 도메인에 맞는 Schema를 설계할 수 있다
  • OpenAI Function Calling 형식의 Schema를 작성할 수 있다

JSON Schema가 뭘까?

집을 짓기 전에 설계도를 그린다. Tool을 만들기 전에 Schema를 그린다.

Schema = "이 Tool을 부르려면 어떤 값을 넣어야 하는지"

Function Calling의 parameters 스키마는 입력만 규정한다. 반환 형식은 스키마가 정하지 않으므로, 무엇을 돌려주는지는 description에 글로 적어야 한다.


기본 타입 6가지

타입         | 예시                 | 제조 현장 예시
─────────────┼──────────────────────┼─────────────────────
string       | "CNC-001"           | 설비 ID, 알람 코드
number       | 45.7                | 온도, 진동, 압력
integer      | 150                 | 수량, 일수, 횟수
boolean      | true                | 포함 여부, 긴급 여부
array        | ["CNC-001","CNC-002"] | 설비 목록, 부품 목록
object       | {"id": "CNC-001"}   | 설비 정보, 필터 조건

Schema 구조 해부

{
  "type": "object",
  "properties": {
    "equipment_id": {
      "type": "string",
      "description": "설비 고유 ID. 형식: TYPE-NNN (예: CNC-001, PRESS-005)"
    },
    "include_alarms": {
      "type": "boolean",
      "description": "활성 알람 포함 여부",
      "default": true
    },
    "days": {
      "type": "integer",
      "description": "조회할 기간 (일 단위). 최소 1, 최대 365",
      "minimum": 1,
      "maximum": 365,
      "default": 7
    }
  },
  "required": ["equipment_id"]
}

각 필드 분석:

필드필수이유
equipment_idO어떤 설비를 조회할지 반드시 알아야 함
include_alarmsX모델이 안 보내면 파이썬 기본 인자가 채운다
daysX모델이 안 보내면 파이썬 기본 인자가 채운다

핵심: required에는 "없으면 Tool이 아예 동작하지 못하는 것"만 넣는다.

함정: 스키마의 default는 API가 값을 채워 주지 않습니다. 모델에게 "안 보내면 대개 이 값으로 본다"고 알려 주는 참고 문구일 뿐입니다. 실제로 값을 채우는 것은 파이썬 함수의 기본 인자(def get_alarm_history(equipment_id: str = "", days: int = 30))입니다. 스키마에만 default를 적고 함수 시그니처를 비워 두면, 모델이 생략한 순간 TypeError가 납니다.


description이 결정적이다

LLM은 description을 읽고 Tool을 선택한다. description이 불분명하면 LLM이 엉뚱한 Tool을 고른다.

나쁜 description

{
  "name": "get_status",
  "description": "상태 조회",
  "parameters": {
    "properties": {
      "id": { "type": "string", "description": "ID" }
    }
  }
}

LLM: "상태? 뭐의 상태? 설비? 주문? 재고? id가 뭐 id?"

좋은 description

{
  "name": "get_equipment_status",
  "description": "제조 설비의 현재 가동 상태를 조회합니다. 설비 ID를 입력하면 가동/비가동/경고 상태, 실시간 가동률(%), 온도(°C), 진동(mm/s), 활성 알람 목록을 반환합니다. 설비 ID 형식은 'CNC-001', 'PRESS-005'입니다.",
  "parameters": {
    "properties": {
      "equipment_id": {
        "type": "string",
        "description": "조회할 설비의 고유 ID. 형식: 설비유형-일련번호 (예: CNC-001, CNC-002, PRESS-005, CONV-010)"
      }
    }
  }
}

LLM: "아, 설비 상태를 조회하는 거구나. CNC-001 형식으로 ID를 넣으면 되겠다."


enum: 선택지를 제한하라

{
  "line": {
    "type": "string",
    "description": "생산 라인 선택",
    "enum": ["A-LINE", "B-LINE", "C-LINE", "ALL"]
  }
}

enum이 없으면 LLM이 "A라인", "A line", "라인A" 등 다양한 형식으로 보낸다. enum으로 제한하면 정확도가 올라간다.


복합 파라미터: 필터 조건

{
  "name": "search_alarm_history",
  "description": "알람 이력을 검색합니다. 설비 ID, 기간, 알람 유형으로 필터링 가능합니다.",
  "parameters": {
    "type": "object",
    "properties": {
      "equipment_id": {
        "type": "string",
        "description": "설비 ID (생략 시 전체 설비 조회)"
      },
      "alarm_type": {
        "type": "string",
        "description": "알람 유형 필터",
        "enum": ["error", "warning", "info", "all"],
        "default": "all"
      },
      "date_range": {
        "type": "object",
        "description": "조회 기간",
        "properties": {
          "start_date": {
            "type": "string",
            "description": "시작일 (YYYY-MM-DD 형식)"
          },
          "end_date": {
            "type": "string",
            "description": "종료일 (YYYY-MM-DD 형식)"
          }
        }
      },
      "limit": {
        "type": "integer",
        "description": "최대 결과 수",
        "default": 50,
        "minimum": 1,
        "maximum": 500
      }
    },
    "required": []
  }
}

strict 모드: 스키마를 지키게 만들기

지금까지의 스키마는 "이렇게 보내 달라"는 요청이다. 모델이 형식을 어겨도 API가 막아 주지 않는다. strict: trueadditionalProperties: false를 함께 쓰면 모델 출력이 스키마를 따르도록 강제된다.

{
  "type": "function",
  "function": {
    "name": "get_equipment_status",
    "description": "설비의 현재 가동 상태를 조회합니다...",
    "strict": true,
    "parameters": {
      "type": "object",
      "properties": {
        "equipment_id": { "type": "string", "description": "설비 ID (예: CNC-001)" }
      },
      "required": ["equipment_id"],
      "additionalProperties": false
    }
  }
}
  • additionalProperties: false: 스키마에 없는 키를 모델이 지어내지 못하게 한다
  • strict: true를 켜면 모든 속성이 required에 들어가야 한다. 선택 파라미터는 "type": ["string", "null"]처럼 null을 허용해 두고, 함수 쪽에서 None을 기본값으로 처리한다

제조 도구는 설비 ID·부품 코드처럼 형식이 정해진 값을 받으므로 strict 모드의 이득이 크다. 스키마를 잡고 나면 켜 두는 편이 낫다.


: 제조 현장에서는 날짜 형식 통일이 중요하다. "1월 15일", "01/15", "2026-01-15" 등 다양한 형식이 올 수 있다. description에 형식을 명시하면 LLM이 맞춰서 보내준다.

AI로 학습하기 — 꿀팁
JSON Schema 속성 정확성 점검AI 학습 팁

본문에서 다룬 strict 모드와 default의 동작을 공식 사양과 대조해 확인하세요.

JSON Schema의 type·properties·required·enum·description 동작이 공식 사양(draft-2020-12)과 일치하는지 확인해줘. 그리고 OpenAI Function Calling에서 (1) 스키마의 default 가 값을 채워 주지 않는다는 설명이 맞는지, (2) strict: true 를 켤 때 additionalProperties: false 와 모든 속성의 required 명시가 왜 함께 요구되는지, (3) 선택 파라미터를 null 허용으로 처리하는 방식이 맞는지 짚어줘.
이 팁이 도움이 됐나요?
용어