OpenAI Structured Outputs로 JSON 파싱 에러 해결

문제 상황

사내 AI 챗봇 백엔드에서 GPT-4o를 사용해 사용자 입력을 구조화된 JSON으로 변환하는 로직이 있었다. response_format: { type: "json_object" }를 사용했지만, 가끔 모델이 불완전한 JSON을 반환해 JSON.parse()에서 에러가 발생했다.

const response = await openai.chat.completions.create({
  model: "gpt-4o",
  messages: [{ role: "user", content: prompt }],
  response_format: { type: "json_object" }
});

try {
  const parsed = JSON.parse(response.choices[0].message.content);
} catch (err) {
  // 여기서 간헐적으로 에러 발생
}

Structured Outputs 도입

OpenAI가 8월 6일에 발표한 Structured Outputs는 JSON Schema를 직접 전달해 100% 유효한 JSON을 보장한다. API 버전을 업그레이드하고 스키마를 정의했다.

const response = await openai.chat.completions.create({
  model: "gpt-4o-2024-08-06",
  messages: [{ role: "user", content: prompt }],
  response_format: {
    type: "json_schema",
    json_schema: {
      name: "user_intent",
      strict: true,
      schema: {
        type: "object",
        properties: {
          intent: { type: "string" },
          parameters: { type: "object" },
          confidence: { type: "number" }
        },
        required: ["intent", "parameters", "confidence"],
        additionalProperties: false
      }
    }
  }
});

const parsed = JSON.parse(response.choices[0].message.content);
// 파싱 에러 완전히 사라짐

결과

배포 후 2주간 모니터링 결과 JSON 파싱 에러가 완전히 사라졌다. strict: true 옵션이 핵심이었다. 기존에 에러 처리를 위해 작성했던 retry 로직도 제거할 수 있었다. 레이턴시는 거의 동일했고, 코드가 훨씬 간결해졌다.