OpenAI Structured Outputs로 JSON 파싱 오류 제거하기

문제 상황

사용자 입력을 분석해서 구조화된 데이터를 추출하는 API를 운영 중이었다. GPT-4o에게 JSON 형식으로 응답하도록 프롬프트를 작성했지만, 간헐적으로 잘못된 형식이 반환되어 JSON.parse() 에러가 발생했다.

const completion = await openai.chat.completions.create({
  model: "gpt-4o",
  messages: [
    { role: "system", content: "Extract user info as JSON" },
    { role: "user", content: userInput }
  ]
});

// 가끔 마크다운 코드블록으로 감싸지거나, 주석이 포함되어 파싱 실패
const data = JSON.parse(completion.choices[0].message.content);

Structured Outputs 적용

8월에 발표된 Structured Outputs를 적용했다. JSON Schema를 정의하면 OpenAI가 스키마를 100% 준수하는 응답을 보장한다.

const completion = await openai.chat.completions.create({
  model: "gpt-4o-2024-08-06",
  messages: [
    { role: "system", content: "Extract user information" },
    { role: "user", content: userInput }
  ],
  response_format: {
    type: "json_schema",
    json_schema: {
      name: "user_info",
      strict: true,
      schema: {
        type: "object",
        properties: {
          name: { type: "string" },
          email: { type: "string" },
          age: { type: "number" }
        },
        required: ["name", "email"],
        additionalProperties: false
      }
    }
  }
});

const data = JSON.parse(completion.choices[0].message.content);

결과

  • 파싱 에러 발생률: 2~3% → 0%
  • 에러 핸들링 코드 제거 가능
  • Function calling보다 간단한 구조

strict: true 옵션이 핵심이다. 이전에 사용하던 response_format: { type: "json_object" }보다 훨씬 엄격한 검증이 적용된다. 프로덕션에 배포 후 일주일간 모니터링했는데 단 한 건의 파싱 오류도 발생하지 않았다.