OpenAI 구조화된 출력 활용 방법

OpenAI의 구조화된 출력은 사용자의 스키마에 맞는 JSON을 보장합니다. `json_schema` + `strict` 대 `JSON mode`, 작동 예시, 제한 사항, 그리고 테스트 방법을 살펴보세요.

INEZA Felin-Michel

INEZA Felin-Michel

26 June 2026

OpenAI 구조화된 출력 활용 방법

Apidog 엔터프라이즈

온프레미스 배포

SSO & RBAC

SOC 2 준수

Apidog Enterprise 살펴보기

이 가이드를 마치면 자신의 코드에서 OpenAI 구조화된 출력을 호출할 수 있게 될 것입니다. 모델에 JSON Schema를 제공하고, `strict: true`를 설정하면, 요청한 형식과 일치함이 보장되는 응답을 받을 수 있습니다. 첫 번째 요청을 보내고, 응답을 읽고, 예외 상황을 처리하며, 페이로드가 실제로 규격을 준수하는지 확인하는 Apidog에서 API 테스트 컬렉션을 생성할 것입니다.버튼

시작하기 전에 필요한 것

구조화된 출력은 모델의 생성을 제한하여 출력이 제공하는 JSON Schema를 따르도록 합니다. `strict: true`와 함께 스키마를 전달하면 모델은 이를 위반하는 필드를 생성할 수 없습니다. 모든 필수 키가 존재하고, 모든 타입이 일치하며, 모든 열거형 값은 나열한 값 중 하나입니다. 방어적인 파싱 코드를 작성하는 것을 멈추고 페이로드를 신뢰하기 시작합니다.

이는 대안보다 훨씬 향상된 기능입니다. "JSON으로만 응답해"와 같은 자유 형식 프롬프트는 작동하다가도 안 될 수 있습니다. 한 번의 추론 오류로 인해 객체 주위에 산문이 붙거나, 정수를 예상한 곳에 날짜가 올 수 있습니다. 구조화된 출력은 계약을 희망적인 지시에서 디코딩 시점에 강제되는 제약으로 전환합니다.

따라오려면 다음이 필요합니다:

올바른 모델 선택

구조화된 출력은 GPT-4o 제품군부터 시작하여 GPT-5 시리즈까지 OpenAI의 최신 모델에서 사용할 수 있습니다. OpenAI 문서는 현재 최신 플래그십 모델(`gpt-5.5`, 이 글 작성 시점 기준)에서 새 프로젝트를 시작하는 것을 권장합니다. 이전 모델과 `gpt-3.5` 시대 모델은 JSON 모드를 지원하지만 엄격한 스키마 강제는 지원하지 않습니다. `strict: true`에 의존하는 경우, 모델 버전과 OpenAI의 업데이트 정책에 따라 지원 여부가 달라지므로 배포하기 전에 특정 모델 ID가 이를 지원하는지 확인하십시오.

OpenAI가 혼동하기 쉬운 두 가지 관련 기능을 제공하므로, 어떤 기능을 실제로 사용하려는지 아는 것이 도움이 됩니다.

JSON 모드 (`response_format: { "type": "json_object" }`)는 출력이 구문적으로 유효한 JSON임을 보장합니다. 그게 전부입니다. 필드, 타입 또는 필수 키를 알지 못합니다. 여전히 직접 형식을 검증해야 합니다.

구조화된 출력 (`response_format`에 `type: "json_schema"` 및 `strict: true`)은 출력이 유효한 JSON임을 보장하고 동시에 스키마와 일치하도록 합니다. OpenAI는 구조화된 출력을 JSON 모드의 진화로 설명합니다. 둘 다 유효한 JSON을 생성하지만, 구조화된 출력만이 스키마 준수를 강제합니다. 새로운 작업에는 구조화된 출력이 원하는 것입니다.

JSON 모드 구조화된 출력 (엄격 모드)
매개변수 response_format: {"type":"json_object"} response_formattype: "json_schema", strict: true
유효한 JSON
스키마 일치 여부 아니요
필수 필드 강제 여부 아니요
타입 및 열거형 강제 여부 아니요
하위에서 여전히 검증 필요 항상 권장됨 (아래 참조)

API 참고 사항: Chat Completions 엔드포인트는 위와 같이 `response_format`을 사용합니다. 새로운 Responses API는 `text.format` 아래에 `type: "json_schema"`로 동일한 내용을 표현합니다. 스키마 규칙은 동일하며, 래퍼만 다릅니다. 호출하는 엔드포인트의 정확한 필드 경로는 최신 문서를 확인하십시오.

첫 번째 요청 보내기

지원 티켓을 유형화된 레코드로 추출한다고 가정해 봅시다. 다음은 엄격한 스키마를 사용하는 Chat Completions 요청입니다.

curl https://api.openai.com/v1/chat/completions \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-5.5",
    "messages": [
      { "role": "system", "content": "Extract the ticket into the schema." },
      { "role": "user", "content": "My checkout 500s every time I use a saved card. Started today. Account: acct_8842." }
    ],
    "response_format": {
      "type": "json_schema",
      "json_schema": {
        "name": "support_ticket",
        "strict": true,
        "schema": {
          "type": "object",
          "properties": {
            "summary":  { "type": "string" },
            "category": { "type": "string", "enum": ["billing", "bug", "account", "other"] },
            "severity": { "type": "integer" },
            "account_id": {
              "anyOf": [ { "type": "string" }, { "type": "null" } ]
            }
          },
          "required": ["summary", "category", "severity", "account_id"],
          "additionalProperties": false
        }
      }
    }
  }'

응답 읽기

모델은 해당 스키마와 일치하는 JSON 문자열을 `content`로 포함하는 메시지를 반환합니다. 예를 들어:

{
  "summary": "Checkout returns HTTP 500 when paying with a saved card",
  "category": "bug",
  "severity": 3,
  "account_id": "acct_8842"
}

`account_id`가 `null`과 함께 `anyOf`를 사용하는 것을 주목하십시오. 이는 선택적 필드를 모델링하는 방법이며, 자신의 스키마를 작성할 때 따라야 하는 규칙으로 바로 연결됩니다.

스키마 하위 집합 내에서 유지

구조화된 출력은 JSON Schema의 하위 집합을 허용합니다. 이 하위 집합은 OpenAI가 제약을 안정적으로 적용하고 컴파일된 스키마를 캐시할 수 있도록 존재합니다. 기억해야 할 규칙은 다음과 같습니다:

유효성 검사 키워드가 강제되지 않으므로, "보장된 JSON"이 "보장된 비즈니스 유효성"을 의미하지는 않습니다. 구조는 고정됩니다. 내부 값은 여전히 테스트할 가치가 있습니다. oneOf/anyOf/allOf로 선택적 또는 유니온 필드를 모델링해 본 적이 있다면, 정신적 모델은 익숙할 것입니다. 스키마는 형식을 제한하지만, 실제 값은 별도로 확인합니다.

거부 및 잘림 처리

출력이 의도적으로 스키마와 일치하지 않는 경우가 한 가지 있습니다. 모델이 안전하지 않은 요청을 거부하면, 스키마 형태의 내용 대신 메시지에 `refusal` 필드를 반환합니다. 코드는 파싱하기 전에 이를 분기해야 합니다:

msg = response.choices[0].message
if msg.refusal:
    handle_refusal(msg.refusal)
else:
    ticket = json.loads(msg.content)

이제 거부를 프로그래밍 방식으로 감지할 수 있어, 사과 메시지를 찾기 위해 텍스트를 스캔하는 것보다 더 깔끔합니다. 응답이 스키마에 미치지 못하는 두 가지 다른 방법은: 객체 중간에 `max_tokens`에 도달하여 JSON이 잘리거나, 구조화된 출력이 지원하지 않는 병렬 도구 호출을 사용하는 것입니다. 이 둘을 결합할 때는 `parallel_tool_calls`를 `false`로 설정하십시오.

Apidog에서 테스트하는 방법

엄격 모드는 생성 시점에 스키마를 강제합니다. 그렇다고 테스트를 면제해 주지는 않습니다. 모델이 바뀌거나, 스키마가 변경되거나, 팀원이 `required` 배열을 편집하거나, 거부 경로가 변경될 수 있습니다. 응답이 계약과 일치하지 않을 때 크게 실패하는 테스트가 필요합니다. 바로 Apidog가 적합한 곳입니다.

정확히 분업을 하자면: OpenAI의 엄격 모드는 스키마에 유효한 JSON을 생성하는 것입니다. Apidog는 모델에서 스키마를 강제하지 않습니다. Apidog는 받은 응답이 예상 스키마와 일치하는지 검증하여, 프로덕션이 아닌 CI에서 변경 사항을 감지할 수 있도록 합니다.

다음은 워크플로입니다:

  1. 요청 보내기. Apidog에서 `response_format` 블록을 사용하여 Chat Completions 호출을 구축하십시오. 반복 가능하도록 컬렉션에 저장하십시오.
  2. 형식 확인. Apidog에 응답 확인을 추가하십시오. `category`가 열거형 값 중 하나인지, `severity`가 정수인지, `account_id`가 문자열 또는 null인지 확인하십시오. Apidog는 응답을 JSON Schema에 대해 검증할 수 있으므로, 정확한 스키마를 첨부하고 페이로드가 벗어날 때 실행을 실패시킬 수 있습니다.
  3. CI에서 실행. 컬렉션을 파이프라인에 넣어 모델이나 프롬프트 변경 시마다 준수 여부를 다시 확인하십시오. 스키마 위반이 조용히 발생하면 빌드가 실패하게 됩니다.
  4. 계약 목업. 실제 호출이 존재하기 전이나, 토큰을 사용하지 않고 하위 소비자를 테스트하기 위해, 스키마에 유효한 샘플 응답을 반환하는 목업 API를 설정하십시오. 통합이 확정되는 동안 프론트엔드와 테스트는 안정적인 형태에 대해 실행됩니다.

마지막 지점은 과소평가된 것입니다. 동일한 스키마를 따르는 목업에 대해 구조화된 출력을 소비하는 모든 것을 개발하고 테스트한 다음, 준비가 되면 실제 OpenAI 호출로 바꿀 수 있습니다. Apidog를 다운로드하면 요청, 어설션 및 목업을 한 곳에서 구축할 수 있습니다.

자주 묻는 질문

구조화된 출력이 존재하는 지금 JSON 모드는 사용 중단되었나요? JSON 모드는 여전히 작동하며 유효한 JSON을 보장합니다. 단지 스키마를 강제하지 않을 뿐입니다. 새로운 코드의 경우, `strict: true`를 사용하는 구조화된 출력이 더 강력한 선택입니다. 엄격한 스키마를 지원하지 않는 모델에서만 또는 고정된 형태가 실제로 없을 때만 일반 JSON 모드를 사용하십시오.

스키마의 루트가 배열일 수 있나요? 아니요. 최상위 레벨은 객체여야 합니다. 목록을 `{"items": [...]}`와 같이 속성으로 래핑하고, `items`를 `required`에 넣으십시오. 많은 사람들이 첫날에 이것으로 어려움을 겪습니다.

필드를 선택 사항으로 만드는 방법은 무엇입니까? 구조화된 출력은 모든 속성이 `required`에 있어야 하므로, 고전적인 선택 사항 필드는 없습니다. "누락됨"을 null 허용으로 모델링하십시오. `string`(또는 다른 유형)과 `null`을 사용하여 `anyOf`를 사용하십시오. 키는 항상 존재하며, 값은 `null`일 수 있습니다.

엄격 모드는 유효성 검사를 완전히 건너뛸 수 있음을 의미합니까? 구조는 보장되므로, 형태 확인은 건너뛸 수 있습니다. 그러나 `pattern`, `format`, 숫자 범위와 같은 키워드는 모델에 의해 강제되지 않으며, 거부 또는 잘림으로 인해 여전히 규격에 맞지 않는 응답이 생성될 수 있습니다. 규격 준수 테스트는 여전히 가치가 있습니다. 이 형식에 익숙하지 않다면, JSON Schema 입문서가 구성 요소를 다루고 있으며, 모든 배포 시에 확인을 실행할 수 있습니다.

어떤 모델을 사용해야 합니까? 구조화된 출력은 GPT-4o 및 이후 모델(GPT-5 시리즈 포함)에서 작동합니다. OpenAI 문서는 현재 플래그십 모델에 새로운 프로젝트를 집중하도록 안내합니다. 엄격 모드 지원은 모델 버전별로 다르므로, 의존하기 전에 정확한 모델 ID가 엄격 모드를 지원하는지 확인하십시오.

마무리

이제 전체 흐름을 이해했습니다: 엄격 모드를 지원하는 모델을 선택하고, `json_schema`와 `strict: true`를 사용하여 Chat Completions 요청을 보내고, 스키마를 지원되는 하위 집합 내에 유지하고, `refusal`에 따라 분기하며, 값 수준 규칙은 여전히 확인해야 함을 기억하십시오. 그런 다음 테스트를 통해 이를 증명하십시오. Apidog에서 요청을 구축하고, 스키마에 대해 응답을 확인하며, 통합이 안정화되는 동안 나머지 스택이 움직일 수 있도록 목업하십시오. 모델은 형태를 약속하고, 테스트는 그 형태가 유지되었음을 증명합니다.

버튼

Apidog에서 API 설계-첫 번째 연습

API를 더 쉽게 구축하고 사용하는 방법을 발견하세요