AI Structured Output이란? GPT·Gemini·Claude가 구조화 JSON을 쓰는 이유

2026년 9월 8일 기준: Structured Output의 의미, GPT / Gemini / Claude가 Schema로 JSON을 제약하는 이유, JSON Mode·Tool Calling과의 차이.

먼저 결론부터: Structured Output은 「JSON을 내라」는 프롬프트가 아니다. API가 디코드 단계에서 JSON Schema로 불법 토큰을 막아, 최종 답을 프로그램이 바로 파싱하게 하는 것이다. GPT, Gemini, Claude가 이를 일급 기능으로 만든 것은 슬라이드에 잘 보여서가 아니라, Agent·추출·폼 입력이 모델을 파이프라인에 꽂아야 하기 때문이다. 산문은 JSON.parse에서 실패한다. 다운스트림 Schema에서는 더 빨리 깨진다.

이 글은 2026년 9월 8일 기준입니다. 세 곳 모두 이제 사용자 / 다음 서비스에 가는 최종 JSON을 제약할 수 있습니다: OpenAI는 response_format.json_schema (strict), Gemini는 responseMimeType + responseJsonSchema, Claude는 GA인 output_config.format (옛 베타 output_format은 전환기에도 동작). 필드를 어떻게 채우는지, subset이 어디서 다른지는 8월에 이미 풀어 썼습니다. 이 글이 답하는 질문은 두 가지뿐입니다: 무엇인지, 그리고 세 곳이 왜 만들 수밖에 없었는지. 적용 단계는 프롬프트에서 Structured Output까지를, OpenAI / Gemini 대조는 Structured Output API 비교를 보세요.

Structured Output이란

Structured Output이란: JSON Schema를 먼저 주고, 모델의 최종 답은 그 Schema에 맞는 JSON이어야 한다는 뜻입니다. 보장은 토큰을 하나씩 생성할 때 일어나며, 생성한 뒤에 「JSON처럼 보이게」 하는 것이 아닙니다. 이름은 다릅니다: OpenAI는 Structured Outputs, Google은 Structured Output, Anthropic 문서는 structured outputs / JSON outputs. s가 하나 더 붙은 것은 브랜딩입니다. 하는 일은 같습니다.

컴파일러와 타입 체커로 기억하세요. 프롬프트는 주석입니다 — 모델이 들을 수도 있습니다. Schema는 타입 시스템입니다 — 잘못된 필드명, 빠진 required, 숫자가 와야 할 자리의 문자열은 디코더가 토큰을 내보내지 않습니다. 프로그램이 받는 것은 객체이지, ```json 울타리 안에 끼워 넣은 산문이 아닙니다.

표현실제 의미흔한 오해
Structured Output최종 답을 JSON Schema에 맞춰 제약 디코딩모델이 똑똑해졌다, 또는 「JSON을 쓸 줄 안다」
JSON Schema필드·타입·필수·enum의 계약더 긴 프롬프트
제약 디코딩생성 중에 불법 토큰을 걸러낸다생성 후 정규식으로 고친다
strict / 강한 제약API가 더 엄한 Schema subset에서 형태를 보장사실이 맞고 숫자를 지어내지 않는다

세 곳이 모두 읽을 수 있는 Schema는 보통 납작합니다: 루트는 object, properties / required를 명시하고, additionalProperties: false. OpenAI strict에서는 「선택」을 required에서 빼기보다 널 가능하게 쓰는 경우가 많습니다. subset은 완전히 같지 않습니다. 먼저 교집합을 잡으세요.

{
  "type": "object",
  "additionalProperties": false,
  "properties": {
    "task": { "type": "string", "enum": ["extract", "classify", "summarize"] },
    "ok": { "type": "boolean" },
    "fields": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "orderId": { "type": "string" },
        "total": { "type": "number" },
        "note": { "type": ["string", "null"] }
      },
      "required": ["orderId", "total", "note"]
    }
  },
  "required": ["task", "ok", "fields"]
}

JSON Mode도 아니고 Tool Calling도 아니다

세 이름이 자주 한 가지로 뭉개집니다. 데이터 흐름에서 같은 층이 아닙니다:

능력보장하는 것보장하지 않는 것
프롬프트 「JSON을 내라」확률을 높인다구문, 필드명, 필수 목록
JSON Mode텍스트가 파싱 가능한 JSON형태, 타입, enum
Structured Output최종 답이 Schema에 맞는다의미가 참인지, 도구가 실행됐는지
Tool Calling도구 인수가 Schema에 맞고 Host가 실행한다사용자에게 가는 최종 답의 형태

JSON Mode는 괄호가 맞고 JSON.parse가 된다는 것만 보장합니다. 모델은 여전히 orderId를 달라고 했는데 order_id를 지어내거나, 금액을 문자열로 낼 수 있습니다. 프로덕션에서 「파싱된다」는 「넣을 수 있다」가 아닙니다.

Tool Calling / Function Calling이 제약하는 것은 도구로 뻗는 손이지, 사용자에게 하는 마지막 문장이 아닙니다. 재고 조회, 파일 쓰기, MCP tools/call은 도구 쪽 Schema입니다. 메일 추출, 티켓 분류, 다운스트림 API에 줄 JSON은 Structured Output입니다. 완전한 Agent는 흔히 둘 다 켭니다 — 인수는 tools, 최종 답은 출력 Schema. 레이어링은 MCP란 무엇인가와 Agent JSON 데이터 흐름을 보세요.

세 곳이 모두 지원하기 시작한 이유

2023년에는 프롬프트에 운을 걸 수 있었습니다. 2026년 Agent는 모델을 루프에 넣습니다: 출력은 데이터베이스, 다음 도구, 다른 벤더의 모델로 갑니다. 세 연구소가 보도자료를 맞춘 것이 아닙니다. 같은 제품 압력이 같은 계약 — JSON Schema — 에 부딪힌 것입니다.

  1. 다운스트림 소비자는 독자가 아니라 프로그램입니다. 채팅은 산문일 수 있습니다. 파이프라인은 객체가 필요합니다. 쉼표 하나, 필드명 한 번 바뀌면 밤새 재시도 큐가 찹니다. 벤더는 고객마다 수리기를 쓰게 두기보다 디코더에서 불법 경로를 잘라 버립니다.
  2. Agent가 「형태가 안정적일 것」을 필수 조건으로 만들었습니다. 다단계 루프에서 직전 턴의 JSON이 이번 턴의 입력입니다. 한 번 표류하면 뒤가 전부 틀립니다. Tool Calling은 「어떻게 손을 뻗을지」를 답합니다. Structured Output은 「결론을 어떻게 돌려줄지」를 답합니다. 둘 다 Schema가 필요합니다 — JSON Schema가 Agent의 표준 Contract가 될까를 보세요.
  3. 프롬프트는 스스로 부족함을 증명했습니다. 「JSON만, 마크다운 금지」는 벤치에서는 예뻐 보이지만, 긴 컨텍스트·도구 재주입·다언어 혼재에서는 필드를 빠뜨리고, 울타리를 붙이고, enum을 유의어로 바꿉니다. 제약 디코딩은 「가끔 실패」를 API 400 또는 재시도 가능한 Schema 오류로 거둡니다.
  4. JSON Schema는 이미 벤더 간 최소 공약수였습니다. OpenAPI, MCP inputSchema, Pydantic / Zod가 내보내는 것이 모두 그것입니다. 모델 쪽에 다른 사설 IDL을 쓰면 Host가 두 번 번역해야 합니다. 최종 답도 같은 Schema에 꽂아야 이전 비용이 떨어집니다.
  5. 경쟁은 「채팅할 수 있나」가 아니라 「프로덕션에 넣을 수 있나」가 됐습니다. 한 벤더가 강한 제약을 내놓으면 게이트웨이, Agent 프레임워크, 기업 구매 목록이 필수 항목으로 적습니다. 나머지 둘이 따라가지 않으면 같은 오케스트레이션에 꽂히지 못합니다. 2026년 9월, Structured Output이 없는 플래그십 API는 행을 넣는 고객에게 팔기 어렵습니다.

그래서 일정이 몰려 있습니다: OpenAI는 2024년 8월 Structured Outputs를 GA로 만들었습니다; Gemini는 MIME + Schema를 생성 설정에 넣었습니다; Claude는 2025년 말까지 베타 헤더였고, 지금은 output_config.format를 정식 필드로 냅니다. 이름은 한 번도 맞지 않았습니다. 압력은 같았습니다.

GPT, Gemini, Claude가 각각 켜는 법

개념은 맞추세요. 필드를 벤더 사이에 복사해 붙이지 마세요. 아래 표는 2026년 9월 8일 문서에 적을 수 있는 입구이지, 완전한 SDK 튜토리얼이 아닙니다.

벤더진입점Schema를 거는 위치2026년에 볼 점
OpenAI (GPT-5.5 등)Chat Completions의 response_format; Responses API의 text.formattype: json_schema + strict: truestrict에서 모든 object는 additionalProperties: false를 원하고, 속성은 보통 모두 required에 들어갑니다; 선택은 널 가능으로
Google (Gemini 3.7 Flash 등)생성 설정의 MIME + SchemaresponseMimeType: application/json + responseJsonSchema (SDK에서는 흔히 response_schema)strict라는 이름의 스위치는 없습니다; 옛 responseSchema는 OpenAPI 대문자 타입을 썼고, 새 채널은 JSON Schema 소문자입니다
Anthropic (Claude 4.6 / 4.8 등)Messages API의 output_config.formattype: json_schema + schema이미 GA — structured-outputs-2025-11-13 헤더는 필요 없습니다; 옛 output_format은 전환기에도 동작. 도구 쪽 strict: true는 Tool Calling이지 최종 답이 아닙니다

요청 포장은 다릅니다. Schema 본체는 같은 파일이어야 합니다. 모델을 바꾸면 바뀌는 것은 바깥 필드이지, orderId와 required가 아닙니다. Claude 스케치 (규격 필드; 업무 Schema는 바꿔 넣으세요):

{
  "model": "claude-sonnet-4-6",
  "max_tokens": 1024,
  "messages": [
    {"role": "user", "content": "Extract orderId and total from the order text"}
  ],
  "output_config": {
    "format": {
      "type": "json_schema",
      "schema": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "orderId": { "type": "string" },
          "total": { "type": "number" }
        },
        "required": ["orderId", "total"]
      }
    }
  }
}

OpenAI는 같은 schema를 response_format.json_schema에 넣고 strict를 켭니다. Gemini는 responseJsonSchema에 넣고 JSON MIME을 선언합니다. 완전한 Python 대조는 여전히 OpenAI vs Gemini에 있습니다. 제품면 (ChatGPT / claude.ai / Gemini 웹)이 같은 강한 제약을 노출하지는 않습니다. SLA는 실제로 호출하는 그 API를 기준으로 쓰세요.

제약 디코딩이 막는 것

Structured Output이 없으면 모델은 전체 어휘에서 샘플링한 뒤, 프롬프트가 JSON처럼 보이게 하기를 바랍니다. Structured Output이 있으면 디코더가 Schema에서 합법 접두사를 유지합니다: 다음 토큰은 여전히 합법한 것만 됩니다 — ", orderId, true, 또는 }. 불법 경로의 확률은 0입니다.

막는 것은 형태입니다: 끝 쉼표, 마크다운 울타리, 빠진 필수 필드, 타입 표류, additionalProperties가 false일 때의 여분 키. 막는 것이 아닌 것은 지어내기입니다: total은 number이지만 값은 지어낼 수 있고, 합법 enum 값도 틀린 것을 고를 수 있습니다. 프로덕션은 같은 Schema로 검증기를 한 번 더 돌립니다. 실패하면 재시도, 강등, 또는 사람입니다. 제약 디코딩이 줄이는 것은 파싱 사고이지, 환각이 아닙니다.

창이 커져도 같습니다. 1M 토큰은 보이는 자료만 늘리고, 출력 형태를 제약하지 않습니다. 덤프를 통째로 넣어도 Schema는 필요합니다 — 1M 토큰 컨텍스트 윈도우를 보세요.

지금 할 일

  1. 먼저 Schema를 쓰고, 그다음 모델을 고르세요. 필드명, 필수, enum이 제품 계약입니다. GPT / Gemini / Claude는 교체 가능한 백엔드입니다. 계약은 저장소에 두고, 프롬프트에 두지 마세요.
  2. 추출, 분류, 폼 입력은 Structured Output. 일을 실행하는 것은 Tool Calling. Structured Output이 재고 API를 이미 친 척하지 마세요. 프로세스를 넘어 도구를 재사용하려면 그때 MCP를 더하세요.
  3. 벤더를 넘길 때는 Schema 교집합을 잡으세요: 납작한 object, additionalProperties: false, 얕은 $ref, 루트 anyOf는 쓰지 마세요. OpenAI strict는 「선택」을 널 가능하게 만듭니다. 세 곳이 서로 표류하는 필드표를 따로 쓰지 마세요.
  4. API가 통과해도 로컬에서 한 번 더 검증하세요. Schema와 2~3조의 정/반례를 JSON으로 저장하고, 이 사이트에서 검증과 Diff를 하세요. 데이터는 업로드되지 않습니다. 제약 디코딩 다음의 두 번째 문입니다.
  5. 실패는 구조로 되돌리세요: 파싱이나 이차 검증이 실패하면 객체로 쓰세요 (어느 필드, 기대 타입). 스택 원문을 다음 턴에 붓지 마세요.

FAQ

Structured Output이 모델에게 JSON을 내라는 뜻인가?

그것만이 아닙니다. 프롬프트나 JSON Mode도 JSON 텍스트를 낼 수 있습니다. Structured Output의 요점은 디코드 단계에서 JSON Schema로 토큰을 거르는 것입니다. 필드명, 타입, 필수는 API가 막으며, 모델이 스스로 지키는 것이 아닙니다.

왜 GPT, Gemini, Claude가 모두 만드나 — 한 벤더면 충분하지 않나?

고객은 다중 모델 장애 조치와 가격 비교를 원합니다. 게이트웨이와 Agent 프레임워크는 이미 「Schema 들어가고, JSON 나온다」로 배선돼 있습니다. 강한 제약이 없는 벤더는 그 파이프라인에 꽂히지 못합니다. 경쟁 압력과 엔지니어링 필요는 같은 사실입니다.

Claude는 지금도 Tool Calling으로 Structured Output을 흉내 내야 하나?

주 경로로는 아닙니다. 2026년 Messages API는 output_config.format로 정식 JSON Schema 출력을 냅니다. 도구 쪽 strict는 여전히 도구 인수만 보장합니다. 옛 베타 헤더와 output_format은 전환기에 남아 있습니다. 새 코드는 output_config를 타세요.

Structured Output을 켰는데도 직접 검증해야 하나?

해야 합니다. 형태와 타입을 보장하지, 값이 참이거나 업무가 합법인지는 보장하지 않습니다. 같은 Schema를 애플리케이션에서 한 번 더 돌리고, 실패하면 재시도하거나 사람에게 올립니다. 브라우저에서는 JSON 툴박스로 샘플을 먼저 맞추세요.

MCP, Tool Calling과 어떻게 고르나?

프로그램에 줄 최종 답: Structured Output. 외부 동작을 실행: Tool Calling. 도구가 다른 프로세스에 있고 Host를 넘어 재사용: MCP. 세 층을 겹칠 수 있습니다. 한 층으로 다른 층을 사칭하지 마세요.

같은 JSON Schema를 세 곳에 그대로 칠 수 있나?

본체는 공유할 수 있고, 요청 포장은 안 됩니다. 납작한 object, 여분 필드 금지, 선택을 널 가능하게 쓰면 성공률이 가장 높습니다. OpenAI strict subset이 가장 엄합니다 — 먼저 그것을 통과시킨 뒤 같은 파일을 Gemini / Claude에 주는 편이, 세 곳이 표류하는 Schema를 따로 유지하는 것보다 쌉니다.

정리

Structured Output은 2026년 플래그십 API의 기본 소켓입니다: 최종 답을 JSON Schema로 제약 디코딩하므로, 프로그램이 프롬프트의 괄호에 더 이상 걸지 않습니다. GPT, Gemini, Claude가 모두 만든 것은 Agent와 추출이 「형태 안정」을 인수 항목으로 썼고, JSON Schema가 세 곳이 이미 아는 계약이기 때문입니다. JSON Mode가 아니며, Tool Calling이나 MCP를 대체하지도 않습니다.

모델을 바꿀 때는 포장 필드만 바꿉니다. 필드명과 required는 저장소에 두고, 배포 전에 같은 Schema로 샘플을 로컬에서 검증하세요. 각 API를 어떻게 맞추고, 도구 층과 어떻게 나누는지는 이 사이트에 이미 있습니다. 이 글은 「무엇인지, 왜인지」만 분명히 합니다.