AI 사전에이전트와 개발

구조화 출력

구조화 출력은 대규모 언어 모델이 자유 형식 글 대신 JSON, XML 같은 미리 정한 형식이나 스키마에 맞춰 응답하도록 하는 기법과 API 기능이다. 생성 단계에서 형식에 어긋나는 토큰을 막는 제약 디코딩이 가장 확실한 구현 방식이다.

루카스 · 수정 · AI Wiki 문서 번역·편집

쉽게 말하면, 구조화 출력은 AI가 자유롭게 글을 쓰는 대신 미리 정해 둔 틀(예: JSON 형식)에 맞춰 답하게 하는 기능이다. 프로그램이 응답을 바로 읽어 쓸 수 있게 해 준다. 틀에 어긋나는 답을 줄이는 가장 확실한 방법은 모델이 단어를 고르는 과정에서 틀에 맞지 않는 선택지를 아예 막는 것이다.

구조화 출력
분류대규모 언어 모델 응답 제어 기법
핵심 방식제약 디코딩으로 형식에 어긋나는 토큰을 생성 단계에서 차단
공식 도입(OpenAI)2024년 8월 6일 Structured Outputs 출시2
대표 형식JSON, XML, 사용자 정의 문법
주요 API 지원OpenAI, Anthropic Claude, Google Gemini2,3,4
주요 오픈소스 도구llama.cpp, Outlines, XGrammar, vLLM5,6,7,8

1. 개요

구조화 출력(Structured output)은 대규모 언어 모델(LLM)이 자유 형식 글 대신 JSON, XML, 사용자 정의 문법처럼 미리 정한 형식이나 스키마에 맞춰 응답하게 하는 기법과 API 기능이다. 가장 신뢰도가 높은 구현은 제약 디코딩(constrained decoding)을 쓴다. 매 생성 단계에서 유효하지 않은 토큰을 가려, 모델이 스키마를 어기는 출력을 수학적으로 만들 수 없게 막는다.

OpenAI는 2024년 8월 6일 Structured Outputs를 내놓으면서 gpt-4o-2024-08-06 모델이 복잡한 JSON 스키마 준수 평가에서 100%를 기록했다고 밝혔다. 같은 평가에서 gpt-4-0613의 점수는 40%에 못 미쳤다.

구조화 출력이 중요해진 이유는 자연어 생성과 프로그램 처리 사이의 간극을 메우기 때문이다. 이 기능이 없으면 개발자는 깨지기 쉬운 파싱 로직을 짜고, 재시도 장치를 만들고, 형식이 깨진 응답을 따로 처리해야 한다. OpenAI는 이 기능이 모델 출력을 개발자가 제공한 JSON Schema와 정확히 일치시킨다고 설명했다.2

2. 작동 원리

구조화 출력 구현은 생성 과정의 여러 단계에서 작동하는 기법들에 기대고 있다. 가장 널리 쓰이는 방식은 토큰을 생성하는 동안 개입하는 제약 디코딩이다. JSON 모드나 프롬프트 지시 같은 가벼운 방식은 생성이 끝난 뒤 출력을 다듬거나 검사하는 데 그친다. 아래 절은 프롬프트 기반 요청에서 엔진 수준의 강제로 이어진 흐름을 따라간다.

3. 등장과 발전

LLM이 API로 쓰이기 시작하자마자 구조화 출력의 필요가 생겼다. 초기에는 「JSON 형식으로만 답하라」 같은 지시를 담은 프롬프트 엔지니어링에 의존했지만 믿을 수 없었다. 모델은 JSON 옆에 설명 문장을 붙이거나, 문법이 틀린 JSON을 내거나, 필수 필드를 빠뜨리는 일이 잦았다. 프롬프트 기반 방식에서 엔진 수준의 강제로 옮겨 간 변화는 LLM 도구 분야에서 가장 중요한 실용적 진전 가운데 하나로 꼽힌다.2

3.1. 함수 호출

OpenAI는 2023년 6월 13일 GPT-3.5 Turbo와 GPT-4 모델 스냅숏(gpt-3.5-turbo-0613, gpt-4-0613)과 함께 함수 호출(function calling)을 도입했다. 개발자가 JSON Schema로 함수를 정의하면 모델은 그 함수를 부르는 데 필요한 인자를 JSON 객체로 만들었다. 이 모델들은 함수 호출이 필요한 시점을 알아차리고, 함수 시그니처에 맞는 JSON으로 답하도록 미세 조정되었다.9

함수 호출은 본래 모델이 외부 도구를 쓰도록 설계된 기능이었지만, 개발자들은 곧 이를 구조화된 데이터를 뽑아내는 범용 수단으로 쓰기 시작했다. 원하는 출력 스키마를 나타내는 함수를 정의하면, 그 함수를 실제로 실행하지 않아도 안정적인 구조의 응답을 얻을 수 있었다.

3.2. JSON 모드

OpenAI는 2023년 11월 6일 첫 DevDay 행사에서 GPT-4 Turbo를 발표하며 JSON 모드를 소개했다. 요청의 response_format 파라미터에 type을 json_object로 지정하면 모델이 문법적으로 올바른 JSON으로 답하도록 할 수 있었다. 다만 JSON 모드는 문법이 맞는 JSON만 보장할 뿐 특정 스키마를 따르도록 강제하지는 않았다. 그래서 필수 필드가 빠지거나, 예상치 못한 속성 이름이 나오거나, 데이터 타입이 틀린 응답이 여전히 가능했다. 개발자는 원하는 구조를 설명하는 프롬프트를 계속 넣고 검증 로직도 따로 만들어야 했다.10

3.3. OpenAI Structured Outputs

OpenAI는 2024년 8월 6일 Structured Outputs를 출시했다. 100% 스키마 준수를 보장한다고 내세운 큰 업그레이드였다. 개발자가 response_format에 type을 json_schema로 지정하고 전체 JSON Schema 정의를 넘기면, 모델은 지정한 구조와 정확히 같은 출력을 만들었다. 복잡한 JSON 스키마 준수 평가에서 새 gpt-4o-2024-08-06 모델은 100%를 기록했고, gpt-4-0613은 40% 미만이었다.

OpenAI는 두 가지 방법을 함께 썼다. 하나는 gpt-4o-2024-08-06 모델을 복잡한 스키마를 더 잘 이해하도록 학습시키는 것이었다. 그래도 회사 내부 벤치마크 정답률은 약 93%에 그쳤고, OpenAI는 이를 실서비스 신뢰성에는 부족하다고 판단했다. 다른 하나는 추론 실행 단계에서 제약 디코딩을 적용하는 것이었다. JSON Schema에서 만든 문맥 자유 문법(CFG)으로 매 단계에서 모델이 낼 수 있는 토큰을 동적으로 제한했다. 스키마는 캐시된 데이터 구조로 미리 처리되어, 생성 중 지연 부담이 적도록 토큰 마스킹을 수행한다.

구조화 출력은 두 가지 형태로 제공된다. 응답을 JSON으로 직접 받는 response_format 파라미터와, 함수 도구 정의에 strict: true를 붙여 함수 호출 인자를 구조화하는 방식이다. 출시 당시 함수 호출 형태는 gpt-4-0613, gpt-3.5-turbo-0613과 이후 모델을 포함해 함수 호출을 지원하는 모든 모델에서 쓸 수 있었다. response_format 형태는 gpt-4o-mini와 gpt-4o-2024-08-06 및 이들의 미세 조정 모델로 제한되었다.2

3.4. OpenAI 모델·API로의 확장

OpenAI는 이후 구조화 출력을 모델 라인업과 API 전반으로 넓혔다. o1 추론 모델은 2024년 12월 17일 API에 나오면서 함수 호출, 개발자 메시지와 함께 이 기능을 얻었다. OpenAI는 o1-2024-12-17 스냅숏이 자체 함수 호출·구조화 출력 평가에서 gpt-4o보다 뚜렷이 나았다고 밝혔다. 2025년 1월 31일 출시된 o3-mini는 회사가 이 기능을 지원한 첫 소형 추론 모델이 되었다. 2025년 3월 11일 에이전트 구축의 권장 인터페이스로 출시된 Responses API는 구조화 출력을 유지하면서 요청 파라미터 이름을 response_format에서 text.format으로 바꿨다.11,12,13

2025년 8월 7일 GPT-5 출시와 함께 OpenAI는 커스텀 도구(custom tools)를 도입했다. 이 도구는 도구 호출을 JSON 대신 평문으로 보내게 하면서, 개발자가 제공한 Lark 또는 정규 표현식 문법으로 그 텍스트를 제한할 수 있게 했다. 커스텀 도구의 문법 강제는 Guidance 라이브러리도 구동하는 오픈소스 Rust 엔진 llguidance로 구현되었다.14,15

3.5. Anthropic Claude

Anthropic은 2024년 Claude 3 모델 계열에 도구 사용(tool use, 함수 호출)을 도입해 도구 정의로 JSON 출력을 제공했다. 2025년 11월 14일에는 Claude Sonnet 4.5와 Opus 4.1을 대상으로 구조화 출력 공개 베타를 발표했다. 이 기능은 JSON 스키마를 문법으로 컴파일해 추론 중 토큰 생성을 제한하며, 프롬프트에만 기대는 방식과 다르다. Anthropic 문서는 이 기능이 Claude의 출력을 제한하는 문법을 만들어 작동하며, 제약 디코딩으로 스키마를 따르는 응답을 보장한다고 밝혔다.3,16

공개 베타는 2025년 11월 14일 베타 헤더 structured-outputs-2025-11-13과 함께 열렸고, 2025년 12월 4일 Claude Haiku 4.5 지원이 추가되었다. 2026년 1월 29일에는 Claude Sonnet 4.5, Opus 4.5, Haiku 4.5를 대상으로 Claude API에서 정식 공개(GA)되었다. 정식 공개와 함께 스키마 지원이 넓어지고 문법 컴파일 지연이 줄었으며 베타 헤더 요구가 사라졌다.16

이 기능은 현재 Claude API에서 정식 공개 상태이고, Amazon Bedrock에서는 Claude Opus 4.6, Sonnet 4.6, Sonnet 4.5, Opus 4.5, Haiku 4.5에서만 제공된다. Anthropic의 2026년 1월 릴리스 노트는 Bedrock과 Microsoft Foundry 버전을 여전히 공개 베타로 적었다. Anthropic은 두 기능을 함께 제공한다. output_config.format으로 응답 형식을 제어하는 JSON 출력과, strict: true로 도구 매개변수 스키마 검증을 보장하는 엄격한 도구 사용이다. 둘을 함께 쓰면 Claude는 한 번의 상호작용에서 유효한 매개변수로 도구를 호출하고 구조화된 JSON 응답을 돌려줄 수 있다.

기존 output_format 파라미터는 정식 공개와 함께 output_config.format으로 바뀌었다. 2026년 9월 기준 Anthropic 문서는 구조화 출력을 Claude API, AWS의 Claude Platform, Amazon Bedrock(Opus 4.6, Sonnet 4.6, Sonnet 4.5, Opus 4.5, Haiku 4.5에 한함), Google Cloud Vertex AI, Microsoft Foundry에서 지원한다고 소개한다. 대상 모델은 Claude Haiku 4.5, Sonnet 4.5, Opus 4.5부터 Claude Opus 4.7, Opus 4.8, Opus 5, Sonnet 5, Fable 5.1, Mythos 5.1까지다.3,16

지원되는 JSON Schema 기능에는 anyOf, allOf, $ref로 만드는 조합과 date-time, email, uuid 같은 문자열 형식이 있다. 재귀 스키마와 minimum, maximum 같은 숫자 범위 제한은 지원되지 않는다.3

3.6. Google Gemini와 기타 제공사

Google은 Google I/O 2024에서 Gemini 1.5 Pro에 제어 생성(controlled generation)을 도입했다. 흔히 JSON 모드 또는 제어 생성이라 불리는 이 기능은 OpenAPI 3.0 스키마 정의에 바탕을 둔 response_schema 파라미터를 쓴다. Gemini API에서 응답 스키마는 출력의 요소, 데이터 타입, 전체 구조를 정하는 템플릿 역할을 한다. 이후 Google은 Gemini 1.5 Flash로 기능을 넓혔고, 2024년 9월 열거형(enum) 지원을 추가했다. 이 기능은 첫 요청에서도 API 호출 지연을 거의 늘리지 않는다. Gemini 2.5 모델부터는 API가 스키마의 키 순서를 출력에 유지한다. 출력 형식은 구조화된 JSON용 application/json과 열거형 응답용 text/x.enum 두 가지다.4,17,18

2025년 11월 5일 Google은 responseJsonSchema 파라미터로 Gemini API에 네이티브 JSON Schema 지원을 추가했고, 현재 지원되는 모든 Gemini 모델에서 쓸 수 있다고 밝혔다. 이 변경으로 OpenAPI 기반 responseSchema가 표현하지 못하던 키워드가 추가되었다. 유니온용 anyOf, 재귀 스키마용 $ref, minimum과 maximum 숫자 범위, additionalProperties, 튜플형 배열용 prefixItems가 그것이다. Pydantic과 Zod 스키마 정의도 변환 없이 API에 넘길 수 있게 되었다. Google은 생성 출력에 스키마의 키 순서를 유지하는 암묵적 속성 순서 기능도 모든 Gemini 2.5 모델과 OpenAI 호환 계층으로 넓혔다.18

구조화 출력은 LLM API 시장의 표준 기능이 되었다. Mistral AI의 API는 strict 플래그를 둔 json_schema 타입의 response_format으로 사용자가 제공한 JSON 스키마를 따르게 하며, 스키마 없는 JSON 모드도 함께 제공한다. xAI의 Grok API도 같은 response_format 방식을 쓰고, 지원되는 스키마 기능을 쓰면 응답이 스키마와 맞는다고 보장한다. Pydantic과 Zod 스키마도 받는다.19,20

4. 핵심 기법

구조화 출력 구현은 생성 과정의 서로 다른 단계에서 작동하는 여러 기법에 기대고 있다. 아래 절은 대표 기법을 차례로 다룬다.

4.1. 제약 디코딩

제약 디코딩(constrained decoding, 유도 디코딩 또는 제약 샘플링이라고도 함)은 대부분의 구조화 출력 구현의 기초 기술이다. 매 생성 단계에서 토큰 확률 분포를 고쳐, 목표 구조를 어기는 토큰이 나오지 않도록 막는다.

  • 생성 전에 목표 스키마나 문법을 유한 상태 기계나 푸시다운 오토마타 같은 내부 표현으로 컴파일한다.
  • 매 디코딩 단계에서 추론 엔진이 현재 상태와 지금까지 생성된 토큰을 바탕으로 유효한 다음 토큰을 정한다.
  • 유효하지 않은 토큰의 로짓 값을 음의 무한대로 설정해 샘플링 확률을 0으로 만든다. 이를 로짓 마스킹 또는 토큰 마스킹이라 한다.
  • 남은 유효 토큰 가운데서 샘플링 온도, Top-p 같은 표준 샘플링 전략으로 하나를 고른다.21

스키마를 미리 처리해 캐시할 수 있으므로 제약 디코딩이 생성 중 더하는 지연은 적다. 이 기법의 구조 강제는 결정적이다. 문법이 다음에 쉼표가 와야 한다고 정하면 쉼표를 포함한 토큰만 0이 아닌 확률을 갖는다.2

4.2. 유한 상태 기계와 정규 표현식

많은 구조화 출력 시스템은 제약을 유한 상태 기계(FSM)로 컴파일한다. 정규 표현식은 수학적으로 FSM과 동등하고, 개발자가 출력 패턴을 명세하기에 편하다. FSM은 현재 상태를 추적하며 어떤 토큰이 유효한 전이로 이어지는지 판단한다. 이 방식은 빠르고 메모리 효율이 좋지만 모든 구조 제약을 표현할 수는 없다. 예를 들어 JSON의 괄호 중첩은 깊이를 세는 스택이 필요해 FSM으로는 강제할 수 없다.

Outlines 라이브러리는 interegular 라이브러리로 JSON 스키마 패턴을 나타내는 정규 표현식을 FSM으로 바꾼다. FSM의 각 상태는 정규 표현식의 한 위치에 대응하고, 유효한 다음 토큰은 올바른 상태 전이를 일으키는 토큰으로 정해진다.22

4.3. 문맥 자유 문법

문맥 자유 문법(CFG)은 정규 표현식과 FSM보다 표현력이 높다. 중첩과 재귀 구조를 나타낼 수 있어 JSON 스키마 준수나 프로그래밍 언어 문법처럼 계층형 형식을 강제하는 데 알맞다. OpenAI의 Structured Outputs도 이 이유로 CFG 기반 방식을 쓴다. CFG 기반 제약 디코딩은 파싱 상태를 추적하기 위해 스택을 덧붙인 FSM인 푸시다운 오토마타를 쓴다. 파서가 토큰마다 스택을 유지하고 갱신해야 하므로 계산 비용은 FSM 방식보다 크다.2,7,21

4.4. 압축 유한 상태 기계

SGLang은 제약 디코딩의 최적화로 압축 유한 상태 기계(compressed FSM)를 도입했다. 시스템은 제약을 분석해 가능한 경우 여러 토큰 경로를 한 번의 전이로 합친다. 예를 들어 특정 위치에서 "name": 문자열이 필요하면 이 문자들을 토큰마다 생성하지 않고 한 단계에 내보낸다. Guidance와 Outlines 기반 JSON 디코딩 파이프라인과 비교한 벤치마크에서 SGLang 팀은 이 점프 전진(jump-forward) 디코딩이 지연 시간을 최대 2배, 처리량을 최대 2.5배 개선했다고 보고했다. 재토큰화 단계가 약 4%의 계산 부담을 더했다.23,24

4.5. 타입 결정만 내는 모델

다른 방식은 자유 텍스트 생성을 제약하는 대신 아예 버린다. TypeSafe AI가 2026년 9월 15일 얼리 액세스로 공개한 Jev는 회사가 「시스템 원 모델(System One Model)」이라 부르는 모델이다. 호출자는 구조화되지 않은 입력(상태)과 타입이 정해진 질문들을 준다. 질문은 보기 중 선택, 정해진 단계의 점수, 회사가 노울(Noul)이라 부르는 예/아니오 질문 세 가지다. 모델은 토큰을 하나씩 만들지 않고 병렬로 한 번에 모든 질문에 답한다. 노울에는 예일 확률을, 선택과 점수에는 보기나 단계별 확률 분포와 이를 바탕으로 한 신뢰도 점수를 준다.25,26

모든 출력이 미리 정의되어 있어 스키마 위반은 구조상 불가능하다. 회사는 이를 「환각 제로(zero hallucinations)」 주장으로 내세우지만, FAQ는 Jev가 답의 형태를 보장할 뿐 모든 판단이 옳다고 보장하지는 않는다고 인정한다. 목록 밖의 범주는 만들 수 없어도 목록 안에서 틀린 범주를 고를 수는 있다고 밝혔다. 회사는 유효한 JSON이 소프트웨어에 읽기 좋은 형식을 주지만 LLM을 그 형식에 억지로 맞추면 지능의 일부를 잃을 수 있다고 주장했다. 이 모델은 처음부터 구조화된 판단을 위해 학습되어 보정된 확률과 함께 타입이 정해진 답을 준다고 설명했다. 모델은 답장을 쓰거나 코드를 만들거나 추론 과정을 설명하지 않으며, 회사는 긴 추론이 필요한 과제는 추론 모델에 맡기는 편이 낫다고 밝혔다. 속도와 비용 배수는 회사 자체 측정치다. 회사의 워크플로 평가에서 Jev의 평균 정확도는 기준 정답 대비 67.8%로, GPT-5.6 Sol(74.1%)과 Claude Opus 5(73.1%)보다 낮았다. 비용과 지연 시간은 이들의 일부 수준에 그친다고 밝혔다.26,27,28

5. 오픈소스 도구와 라이브러리

여러 오픈소스 라이브러리가 로컬에서 호스팅되는 모델의 구조화 출력 생성을 지원한다. 이들 가운데 상당수는 상용 API 기능과 비슷하거나 그 이상의 기능을 제공한다.

llama.cpp는 로컬에서 LLM을 돌리는 데 널리 쓰이는 C/C++ 추론 엔진으로, GBNF(GGML BNF)를 이용한 문법 제약 생성을 지원한다. GBNF는 바커스-나우르 형식(BNF)에 문자 범위와 반복을 나타내는 정규식 비슷한 확장을 더한 형식이다. 개발자가 유효한 출력 순서를 정의하는 문법 규칙을 쓰면, 추론 엔진은 매 단계에서 그 문법을 만족하는 토큰만 고르게 한다.5

root   ::= "{" ws "\"name\"" ws ":" ws string "," ws "\"age\"" ws ":" ws number "}"
string ::= "\"" [a-zA-Z ]+ "\""
number ::= [0-9]+
ws     ::= [ \t\n]*
name과 age 필드를 가진 JSON 객체의 GBNF 문법 예시

llama.cpp에는 JSON Schema 정의를 GBNF 문법으로 자동 변환하는 json-schema-to-grammar.py 유틸리티도 있다. Python 바인딩(llama-cpp-python)은 0.1.78 버전부터 LlamaGrammar 클래스로 이 기능을 노출한다. 문법 제약 생성 덕분에 개발자는 더 작고 저렴한 로컬 모델을 쓰면서도 안정적인 구조화 출력을 얻을 수 있다.5

Outlines는 dottxt가 개발한 구조화 생성용 Python 라이브러리로, Brandon Willard와 Remi Louf가 만들었다. 정규 표현식과 FSM의 수학적 동등성을 이용해 토큰 단위로 생성을 제약한다. 생성 후 검증하고 실패하면 재시도하는 대신, 무효 토큰이 처음부터 생성되지 않도록 막는다. 저자들은 이렇게 생성 시점에 검증하는 방식이 추론 중 추가 비용이 거의 없음을 보였다.22

Outlines는 JSON 스키마(Pydantic 모델 기반), 정규 표현식, 문맥 자유 문법, 선택지 제약을 지원한다. JSON 스키마는 interegular 라이브러리로 정규 표현식으로 바뀐 뒤 FSM이 되어 토큰 단위로 강제된다. Index 객체는 어휘(Vocabulary)와 정규 표현식을 합쳐, 주어진 어휘의 토큰을 유한 상태 오토마톤의 상태 전이에 효율적으로 대응시킨다. 핵심 알고리즘은 성능을 높이려고 Hugging Face와 협업해 개발한 outlines-core 패키지에서 Rust로 옮겨졌다. Hugging Face Transformers, vLLM, Ollama 등 여러 백엔드와 호환된다. Outlines v1.0.0은 2025년 6월 18일 공개되었다. 공개 API를 통합 Generator 인터페이스 중심으로 다시 썼고, 라이브러리의 초점을 제약 생성으로 좁혔다. 모델 로딩과 샘플링 제어는 하부 추론 라이브러리에 맡겼다.6,29,30

XGrammar는 MLC 팀이 개발한 고성능 구조화 생성 엔진으로, JSON 스키마, 정규 표현식, 임의의 문맥 자유 문법을 지원한다. 토큰마다 40마이크로초 미만으로 토큰 마스크를 계산해 JSON 생성의 오버헤드를 거의 없는 수준으로 낮춘다. 벤치마크에서 JSON 스키마 작업은 이전 솔루션보다 최대 3.5배, CFG 작업은 최대 10배 빨랐다. 엔드투엔드 평가에서는 JSON 스키마 생성에서 기존 LLM 엔진보다 최대 14배, CFG 유도 생성에서 최대 80배 빨랐다.7,31

2025년 초까지 XGrammar는 MLC-LLM과 SGLang에 통합되었고, vLLM의 기본 구조화 생성 백엔드가 되었다(Outlines로 되돌아가는 폴백 포함). MLC 팀은 TensorRT-LLM 통합이 진행 중이라고 밝혔다. C++ 코어 덕분에 서버, 노트북, 엣지 플랫폼에서 실행된다.21,31

Guidance는 Microsoft가 만든 오픈소스 Python 라이브러리로, LLM 출력을 제어하는 도메인 특화 언어를 제공한다. 생성, 프롬프트, 논리 제어를 하나의 연속된 흐름으로 엮고, 추론 계층에서 토큰 단위로 모델을 조정해 제약을 강제한다. 생성 후 파싱에 기대는 일반 프롬프트 기법과 다른 점이다. select(보기 중 선택), 정규 표현식, 문맥 자유 문법을 지원한다. 동반 라이브러리 llguidance는 토큰당 CPU 시간 약 50마이크로초 수준으로 제약 디코딩을 구현한다. 프로젝트는 생성과 제어 로직을 한 흐름에서 실행하므로 일반 프롬프트나 미세 조정보다 지연과 비용을 줄인다고 설명한다. LLaMA, GPT-2, Alpaca 같은 로컬 오픈소스 모델과 ChatGPT, GPT-4 같은 폐쇄형 API 모델을 모두 쓸 수 있다.15,32

LM Format Enforcer는 Noam Gat이 만든 라이브러리로, 문자 단위 접근을 쓴다. 문자 단위 파서와 토크나이저 접두사 트리를 결합해, 유효한 출력으로 이어질 수 있는 문자를 포함한 토큰만 허용한다. 매 단계에서 파서가 현재 제약에 따라 추가할 수 있는 문자를 제한한다. 예를 들어 JSON을 만들 때 여는 중괄호 뒤에는 공백, 닫는 중괄호, 속성 이름을 시작하는 따옴표만 올 수 있다. JSON Schema, 스키마 없는 JSON 모드, 정규 표현식 형식을 지원하며 Transformers, LlamaIndex, LangChain, llama.cpp, vLLM, Haystack, NVIDIA TensorRT-LLM과 함께 쓸 수 있다. 출력 로짓에만 작용하고 생성 루프를 바꾸지 않으므로 빔 서치와 배치 처리 같은 생성 방식도 지원한다.33

6. 추론 엔진의 지원

최신 LLM 추론 엔진은 구조화 출력 기능을 내장하고 있어, 추가 라이브러리 없이도 제약 디코딩을 쓸 수 있다.

vLLM은 여러 백엔드를 통해 구조화 출력을 지원한다. 백엔드에는 XGrammar(기본값), Outlines, LM Format Enforcer, Guidance가 있다. 기본값인 auto 모드는 요청에 따라 최선의 백엔드를 고른다. OpenAI 호환 API는 guided_json, guided_regex, guided_choice, guided_grammar 파라미터를 받는다. Python API에서는 SamplingParams.guided_decoding 아래에 제약을 지정한다. vLLM V1의 구조화 출력 성능은 V0보다 크게 빨라졌다. V0에서는 제약 요청 하나가 시스템 전체 성능을 떨어뜨릴 수 있었지만, V1은 백엔드 최적화와 더 나은 구조로 오버헤드를 최소화한다.8,21

SGLang은 압축 유한 상태 기계로 효율적인 제약 디코딩을 구현한다. regex 인자로 정규 표현식 제약을 걸 수 있고, JSON 스키마 제약도 지원한다. XGrammar와 llguidance를 문법 백엔드로 활용할 수 있으며, RadixAttention 기반 프리픽스 캐싱으로 비슷한 스키마를 반복하는 구조화 생성 요청을 더 최적화한다.23

7. 스키마 정의 도구

개발자는 보통 원시 JSON Schema를 직접 쓰기보다 스키마 정의 라이브러리로 출력 구조를 정의한다. 이 라이브러리들은 타입 안전성, 검증, 자동 스키마 생성을 제공한다.

7.1. Pydantic과 Zod

Pydantic은 Python 생태계에서 구조화 출력에 가장 널리 쓰이는 스키마 정의 라이브러리다. 개발자는 타입이 지정된 필드를 가진 Python 클래스를 정의하고, Pydantic은 그 구조에서 JSON Schema를 자동으로 만든다. 런타임 검증도 제공한다. 모델이 출력을 만든 뒤 Pydantic이 JSON을 파싱해 스키마와 맞는지 확인하고, 실패하면 자세한 오류 메시지를 준다. Instructor, Outlines, OpenAI Python SDK를 포함한 대부분의 Python 구조화 출력 라이브러리가 Pydantic 모델을 스키마 정의로 받는다.6,34

from pydantic import BaseModel
from typing import Optional

class Address(BaseModel):
    street: str
    city: str
    state: str
    zip_code: str

class UserInfo(BaseModel):
    name: str
    age: int
    email: str
    phone: Optional[str] = None
    address: Address
    interests: list[str]
Pydantic 모델 예시

이 모델 정의는 중첩 객체, 선택 필드, 배열 타입, 문자열과 정수 제약을 포함한 JSON Schema를 자동으로 만든다. 같은 클래스가 LLM에 보내는 스키마 정의와 응답 검증에 함께 쓰인다.

Zod는 TypeScript와 JavaScript 생태계에서 같은 역할을 한다. TypeScript 우선 스키마 검증과 정적 타입 추론을 제공해, Zod 스키마 하나가 실행 시점의 검증기와 컴파일 시점의 TypeScript 타입을 함께 만든다. 타입 정의와 검증 로직이 어긋나는 문제를 없앤다. OpenAI Node.js SDK, Vercel AI SDK 등 TypeScript LLM 라이브러리가 Zod 스키마를 받는다. Zod 스키마를 넘기면 응답에 검증되고 타입이 정해진 결과를 담은 parsed 필드가 포함된다.

8. 고수준 라이브러리

Instructor는 LLM에서 구조화 데이터를 추출하는 데 가장 널리 쓰이는 Python 라이브러리다. Jason Liu가 만들었고, 2023년 6월 「OpenAI Function Call and Pydantic Integration Module」이라는 이름으로 오픈소스화되었다. 월간 다운로드 300만 회 이상, GitHub 스타 11,000개 이상으로 성장했다. OpenAI 팀은 Structured Outputs 기능의 영감으로 Instructor를 언급했다. Instructor는 LLM API 호출에 Pydantic 모델 검증, Tenacity 라이브러리를 이용한 자동 재시도, 부분 응답 스트리밍 지원을 더해 감싼다.2,34

Instructor는 response_model 파라미터로 Pydantic 클래스를 받아 원하는 출력 구조를 정의한다. 제공자에 따라 함수 호출, 도구 사용, JSON Schema 중 맞는 API 형식으로 바꾼다. 출력이 검증에 실패하면 오류 내용을 프롬프트에 넣어 자동으로 재시도하므로, 모델이 무엇이 틀렸는지 알 수 있다. 15개 이상의 제공자를 지원하며 OpenAI, Anthropic, Google, Ollama, DeepSeek 등이 포함된다. Island AI를 만든 Dimitri Kennedy와 협업한 TypeScript 버전도 있다.34

LangChain은 with_structured_output() 메서드로 구조화 출력을 제공한다. Pydantic 모델, TypedDict 클래스, 원시 JSON Schema 정의를 받는다. 내부에서는 제공자별로 방식을 고른다. 도구 호출을 지원하면 도구 호출을, JSON 모드가 있으면 JSON 모드를 쓰고, 그 밖에는 프롬프트 기반 추출로 대체한다. 개발자는 스키마 정의를 바꾸지 않고 제공자를 바꿀 수 있다.35

9. 제공사별 구조화 출력 기능 비교

제공사별 기능 비교 · 2026년 초 기준
기능OpenAIAnthropic(Claude)Google(Gemini)
JSON 모드있음(2023년 11월)있음있음3,10,17
JSON 스키마 강제있음(2024년 8월)있음(2025년 11월 베타, 현재 정식 공개)있음(Google I/O 2024)2,16,18
함수·도구 호출있음(2023년 6월)있음(2024년)있음3,4,9
도구용 엄격 모드strict: truestrict: true함수 호출 시 자동 적용2,3,4
스키마 정의 형식JSON SchemaJSON SchemaOpenAPI 3.0 스키마2,3,17
제약 디코딩 방식CFG 기반문법 기반있음2,3,4
열거형 지원있음있음있음
중첩 객체있음있음있음
재귀 스키마있음($ref 사용)지원 안 함있음($ref, 2025년 11월부터)2,3,18
스트리밍 지원있음있음있음
키 순서 보존있음(스키마 순서)보장 없음있음(Gemini 2.5 이상)2,18

10. 함수 호출과 구조화 출력의 관계

함수 호출(또는 도구 호출)은 LLM에서 구조화 출력을 얻는 가장 먼저 널리 쓰인 방법이었다. 함수 호출은 모델이 외부 함수를 부르도록 설계되었지만, 개발자들은 원하는 출력 스키마를 가진 함수를 정의하고 모델이 늘 그 함수를 부르도록 설정하면 구조화된 응답을 사실상 강제할 수 있다는 것을 알아냈다. 그 함수는 실제로 실행될 필요가 없었다.9

이 패턴은 모델이 함수의 매개변수 스키마에 맞는 JSON 객체를 만들어야 한다는 점에서 작동한다. OpenAI는 2024년 8월 이 패턴을 Structured Outputs로 정식화했다. 함수 정의에 strict: true를 설정하면 생성된 인자가 JSON Schema와 정확히 일치하도록 보장된다. 이 기능은 함수 호출을 지원하는 OpenAI 모델 전체에서 쓸 수 있으며, gpt-4o, gpt-4o-mini와 gpt-4-0613 이후의 모든 모델이 포함된다.2

Anthropic과 Google은 각자의 도구 사용 API로 비슷한 기능을 제공한다. 이 API들에서는 도구 입력 스키마가 함수 매개변수 스키마와 같은 역할을 한다.3

11. 구조화 출력의 활용

구조화 출력은 자유 형식 텍스트 생성으로는 어렵거나 불가능한 여러 실서비스 응용을 가능하게 한다.

LLM을 백엔드 서비스로 쓰는 애플리케이션은 일관되고 기계가 읽을 수 있는 응답 형식이 필요하다. 구조화 출력은 모든 API 응답이 기대한 스키마와 맞도록 보장해, 파싱 휴리스틱과 오류 복구 코드를 줄인다. 특정 데이터 계약을 기대하는 다른 서비스와 상호운용해야 하는 마이크로서비스 구조에서 특히 중요하다.

데이터 추출도 가장 흔한 용도다. 이메일, 법률 문서, 진료 기록 같은 글에서 이름, 날짜, 금액, 범주 같은 필드를 미리 정한 스키마에 안정적으로 뽑아낼 수 있다. 취약하고 유지 비용이 큰 수작업 입력과 규칙 기반 추출 시스템을 대체한다.

AI 에이전트는 유효한 도구 호출을 만들기 위해 구조화 출력에 의존한다. 에이전트가 웹을 검색하거나 데이터베이스를 조회하거나 API를 호출하려면 정확한 형식의 요청을 만들어야 한다. 구조화 출력은 도구 호출 인자가 도구 매개변수 스키마에 맞는 유효한 JSON임을 보장해, 다단계 워크플로에서 실행 오류를 막는다. 구조화 출력이 없다면 에이전트 시스템은 형식이 깨진 도구 호출을 처리하는 광범위한 오류 처리가 필요하다.

구조화 출력은 응답을 미리 정한 범주 집합으로 제한해 분류 작업을 단순하게 만든다. 열거형 제약이나 선택 파라미터를 쓰면 모델은 자유롭게 만든 라벨 대신 유효한 보기 중에서 골라야 한다. 감성 분석, 콘텐츠 검수, 의도 탐지 같은 범주화 작업에 유용하다.

문법 제약 생성으로 생성된 코드의 문법적 유효성을 강제할 수 있다. 대상 프로그래밍 언어의 문맥 자유 문법을 정의하면 모델은 문법적으로 잘못된 코드를 만들 수 없다. 다만 의미적 정확성은 여전히 모델의 능력에 달려 있다.

스키마가 보고서 형식을 정의하면 LLM은 일관된 절, 제목, 데이터 표를 갖춘 보고서를 만들 수 있다. 엄격한 서식을 따라야 하는 금융, 의료, 컴플라이언스 분야에서 특히 유용하다.

12. 신뢰성과 검증

구조화 출력은 제약 디코딩으로 강한 구조적 보장을 주지만, 실서비스 시스템은 여전히 검증 계층을 두어야 한다.

구조화 출력은 생성된 데이터가 문법적으로 유효하고 지정한 스키마와 맞는다는 것만 보장한다. 내용이 사실이거나 논리적으로 일관되거나 의미상 맞다는 것까지 보장하지는 않는다. 모델은 형식이 완벽한 JSON 안에 비현실적인 temperature 값을 넣거나, 문법은 맞지만 존재하지 않는 이메일 주소를 쓸 수 있다. 구조적 정확성과 의미적 정확성을 구분하는 것이 제약 디코딩의 한계를 이해하는 출발점이다.

생산 시스템은 보통 제약 디코딩에 추가 검증을 결합한다. 아래 표는 검증 계층별로 확인하는 내용과 예시 도구를 정리한 것이다.

검증 계층별 확인 내용과 예시 도구
검증 계층확인하는 내용예시 도구
스키마 검증JSON 구조가 스키마와 맞는지Pydantic, Zod, JSON Schema 검증기
타입 검사필드 값의 타입이 맞는지Pydantic 타입 강제 변환, Zod 파싱
범위·제약 검증값이 허용 범위 안에 있는지Pydantic 필드 검증기, 사용자 정의 검사
의미 검증내용이 업무 논리에 맞는지응용별 업무 로직
교차 필드 검증관련 필드끼리 일관된지Pydantic 모델 검증기
외부 검증실제 출처 데이터와 맞는지데이터베이스 조회, API 확인

제약 디코딩을 써도 가장자리 사례는 생긴다. 예를 들어 모델이 JSON 구조를 끝내기 전에 최대 토큰 수에 닿을 수 있다. Instructor 같은 라이브러리는 자동 재시도를 구현한다. 검증에 실패하면 오류 메시지를 원래 프롬프트와 함께 모델에 다시 넣어 스스로 고칠 기회를 준다. 재시도 횟수는 무한 반복을 막기 위해 보통 2~3회로 설정한다. 이렇게 하면 모델이 자기 수정에 충분한 기회를 얻으면서도 루프가 끝없이 돌지 않는다.34

제약 디코딩은 출력 품질에 미묘한 영향을 줄 수 있다. 매 단계 토큰 공간을 제한하므로, 제약이 없을 때보다 덜 자연스럽거나 덜 정확한 내용이 나올 수도 있다. 데이터 추출처럼 구조가 중요한 작업에서는 이 절충이 대체로 받아들여지지만, 구조화된 형식 안에서 창의적인 글을 써야 하는 작업에는 문제가 될 수 있다. 벤치마크 결과에 따르면 잘 설계된 스키마에서는 품질 영향이 미미하고, 신뢰성 이득이 작은 품질 차이를 훨씬 넘는다.

제약 디코딩이 모델 능력을 해치는지는 활발한 연구 주제가 되었다. 2024년 Appier와 국립대만대학교 연구자들이 EMNLP 2024 산업 트랙에서 발표한 「Let Me Speak Freely?」는 형식 제한 아래에서 LLM의 추론 성능이 크게 떨어진다고 보고했다. 형식 제약이 엄격할수록 추론 과제의 성능 저하가 대체로 컸다. Outlines를 만든 dottxt 연구자들은 「Say What You Mean」이라는 반론에서, 격차가 구조 자체보다 프롬프트 설계와 불공정한 비교에서 나왔다고 주장했다. 다시 실험한 결과에서는 구조화 생성이 비구조화 생성과 같거나 더 나았다고 제시했다.36,37

이론 연구도 토큰 마스킹이 모델의 확률 분포와 어떻게 상호작용하는지 검토했다. NeurIPS 2024에서 발표된 Grammar-Aligned Decoding은 표준 문법 제약 디코딩이 모델 분포를 왜곡해, 문법에는 맞지만 모델이 부여한 확률에 비례하지 않는 출력을 낸다고 보였다. 이 연구는 문법 제약 아래에서 모델의 조건부 분포에 수렴함이 증명된 ASAp 샘플링 알고리즘을 제시했다. 2025년 1월 EPFL과 Microsoft 연구자들은 JSONSchemaBench를 공개했다. 약 1만 개의 실제 JSON 스키마를 공식 JSON Schema 테스트 스위트와 짝지은 벤치마크로, Guidance, Outlines, llama.cpp, XGrammar, OpenAI와 Gemini API 여섯 구조화 출력 프레임워크를 효율, 스키마 적용 범위, 출력 품질 면에서 비교했다.38,39

13. 한계와 과제

구조화 출력은 큰 진전을 이뤘지만 여전히 여러 과제에 직면한다.

매우 크거나 깊이 중첩된 스키마는 토큰마다 문법이나 FSM을 평가하는 일이 복잡해져 지연을 키울 수 있다. OpenAI는 전처리와 캐싱으로 이를 완화하지만, 새 스키마의 첫 요청은 컴파일에 따른 추가 지연을 겪는다.2

대부분의 제공사는 JSON Schema 전체가 아니라 일부만 지원한다. 예를 들어 OpenAI의 Structured Outputs는 모든 필드를 필수로 표시해야 하며, 선택 필드는 유니온 구문으로 nullable 타입을 써야 한다. 일부 제공사는 재귀 참조나 if/then/else 같은 조건 키워드를 지원하지 않는다.

모델이 구조화 출력을 끝내기 전에 최대 출력 토큰 한도에 닿으면 결과가 잘려 유효하지 않게 된다. finish_reason 필드가 stop이 아니라 length로 나오는지 보면 이를 감지할 수 있다. 개발자는 복잡한 스키마에 넉넉한 max_tokens 값을 설정하는 것이 좋다.

매 단계에서 유효한 토큰이 거의 남지 않을 만큼 제약이 과하면 생성 내용의 품질이 떨어질 수 있다. 구조 안에서 모델이 충분한 표현 자유를 가질 수 있도록 스키마를 설계하면 더 나은 결과가 나온다.

요청 시점에 스키마를 문법으로 컴파일하는 제공사와 엔진에서는 새 스키마의 첫 요청이 더 느려질 수 있다. 이후 요청은 캐시의 도움을 받는다. XGrammar 같은 엔진은 문법의 재사용 가능한 부분을 미리 계산해 이 지연을 부분적으로 줄인다.7

출처 39개
  1. AI Wiki: Structured output (2026-09-16 수정본) aiwiki.ai · CC BY 4.0 · 확인 2026-10-15
  2. Introducing Structured Outputs in the API (AI Wiki 인용) openai.com · 확인 2026-10-15
  3. Structured outputs (AI Wiki 인용) platform.claude.com · 확인 2026-10-15
  4. Mastering Controlled Generation with Gemini 1.5: Schema Adherence for Developers (AI Wiki 인용) developers.googleblog.com · 확인 2026-10-15
  5. llama.cpp grammars (AI Wiki 인용) github.com · 확인 2026-10-15
  6. Outlines: Structured Outputs (AI Wiki 인용) github.com · 확인 2026-10-15
  7. XGrammar: Flexible and Efficient Structured Generation Engine for Large Language Models (AI Wiki 인용) arxiv.org · 확인 2026-10-15
  8. Structured Outputs (AI Wiki 인용) docs.vllm.ai · 확인 2026-10-15
  9. Function calling and other API updates (AI Wiki 인용) openai.com · 확인 2026-10-15
  10. New models and developer products announced at DevDay (AI Wiki 인용) openai.com · 확인 2026-10-15
  11. OpenAI o1 and new tools for developers (AI Wiki 인용) openai.com · 확인 2026-10-15
  12. OpenAI o3-mini (AI Wiki 인용) openai.com · 확인 2026-10-15
  13. New tools for building agents (AI Wiki 인용) openai.com · 확인 2026-10-15
  14. Introducing GPT-5 for developers (AI Wiki 인용) openai.com · 확인 2026-10-15
  15. llguidance: Super-fast Structured Outputs (AI Wiki 인용) github.com · 확인 2026-10-15
  16. Claude API release notes (AI Wiki 인용) platform.claude.com · 확인 2026-10-15
  17. Structured outputs (AI Wiki 인용) ai.google.dev · 확인 2026-10-15
  18. Improving Structured Outputs in the Gemini API (AI Wiki 인용) blog.google · 확인 2026-10-15
  19. Custom Structured Outputs (AI Wiki 인용) docs.mistral.ai · 확인 2026-10-15
  20. Structured Outputs (AI Wiki 인용) docs.x.ai · 확인 2026-10-15
  21. Structured Decoding in vLLM: a gentle introduction (AI Wiki 인용) blog.vllm.ai · 확인 2026-10-15
  22. Efficient Guided Generation for Large Language Models (AI Wiki 인용) arxiv.org · 확인 2026-10-15
  23. SGLang: Efficient Execution of Structured Language Model Programs (AI Wiki 인용) arxiv.org · 확인 2026-10-15
  24. Fast JSON Decoding for Local LLMs with Compressed Finite State Machine (AI Wiki 인용) lmsys.org · 확인 2026-10-15
  25. Introducing System One Models & Jev (AI Wiki 인용) typesafe.ai · 확인 2026-10-15
  26. System One (AI Wiki 인용) docs.typesafe.ai · 확인 2026-10-15
  27. We give a FAQ (AI Wiki 인용) typesafe.ai · 확인 2026-10-15
  28. Workflow evals: Structured workflows for automation tasks (AI Wiki 인용) evals.typesafe.ai · 확인 2026-10-15
  29. outlines-core (AI Wiki 인용) github.com · 확인 2026-10-15
  30. Outlines v1.0.0 release notes (AI Wiki 인용) github.com · 확인 2026-10-15
  31. Achieving Efficient, Flexible, and Portable Structured Generation with XGrammar (AI Wiki 인용) blog.mlc.ai · 확인 2026-10-15
  32. Guidance: A guidance language for controlling large language models (AI Wiki 인용) github.com · 확인 2026-10-15
  33. LM Format Enforcer (AI Wiki 인용) github.com · 확인 2026-10-15
  34. Instructor: structured outputs for LLMs (AI Wiki 인용) github.com · 확인 2026-10-15
  35. How to return structured data from a model (AI Wiki 인용) python.langchain.com · 확인 2026-10-15
  36. Let Me Speak Freely? A Study on the Impact of Format Restrictions on Performance of Large Language Models (AI Wiki 인용) arxiv.org · 확인 2026-10-15
  37. Say What You Mean: A Response to 'Let Me Speak Freely' (AI Wiki 인용) blog.dottxt.co · 확인 2026-10-15
  38. Grammar-Aligned Decoding (AI Wiki 인용) arxiv.org · 확인 2026-10-15
  39. JSONSchemaBench: A Rigorous Benchmark of Structured Outputs for Language Models (AI Wiki 인용) arxiv.org · 확인 2026-10-15