AI가 JSON 형식을 자꾸 바꿀 때, 구조화된 출력을 쓰는 법

AI 생성 사진풍 이미지: AI가 JSON 형식을 자꾸 바꿀 때, 구조화된 출력을 쓰는 법 8

AI를 활용하여 생성한 이미지입니다.

앱이 매번 같은 필드를 읽어야 한다면 ‘JSON으로 답해 주세요’라는 문장만으로는 부족합니다. 구조화된 출력과 JSON Schema를 사용해 키, 타입, 허용값을 먼저 정하고, 그 뒤에 원문과 사실을 검증해야 합니다. 형식을 맞추는 기능이 내용의 진실까지 보증하지는 않습니다.

먼저 구분해야 할 세 가지

일반 텍스트 응답은 사람이 읽기에는 편하지만 프로그램에 넘길 때 필드 누락, 타입 변화, 설명 문장 혼입이 생길 수 있습니다. JSON mode는 유효한 JSON을 만들도록 돕는 방식이고, 구조화된 출력은 개발자가 정의한 Schema에 맞는 객체를 요구하는 방식입니다. OpenAI는 Structured Outputs가 제공된 JSON Schema를 따르도록 돕는다고 설명하고, Google도 Gemini의 구조화된 출력이 예측 가능한 유형의 결과를 만드는 데 쓰인다고 안내합니다.[1][2]

구분 확인하는 것 남는 위험
일반 프롬프트 모델에게 형식을 글로 설명 키·타입·설명 문장이 흔들릴 수 있음
JSON mode JSON으로 파싱 가능한지 필수 키와 업무 규칙은 별도 확인
구조화된 출력 Schema의 구조와 타입 잘못된 날짜·분류·숫자는 여전히 가능

예를 들어 urgent를 boolean으로 정했다면 true 또는 false를 기대합니다. ‘예’, ‘아니요’, ‘yes’를 문자열로 받아 저장하면 다음 코드가 조건문에서 다르게 동작할 수 있어요. 반대로 category가 허용 목록에 들어 있어도 실제 문의를 올바르게 분류했다는 뜻은 아닙니다.

구조화된 출력이 잘 맞는 작업

결과를 데이터베이스에 저장하거나 화면의 카드·필터로 보여 주거나, 다른 API 호출의 입력으로 넘길 때 효과가 큽니다. 이름·날짜 추출, 사전 정의된 범주 분류, 도구 호출용 인자 생성이 대표적인 예입니다.[2]

작업 추천도 설계 포인트
고객 문의 분류 높음 category, priority, unknown 상태를 분리합니다.
영수증 추출 높음 금액·통화·세금 포함 여부를 나눕니다.
상품 데이터 정리 높음 가격의 기준일과 단위를 함께 저장합니다.
이메일 초안 낮음 자연스러운 문장이 목적이면 일반 응답이 간단합니다.
긴 글 요약 상황에 따라 요약문만 필요한지 근거 필드도 필요한지 정합니다.

Schema를 설계하는 순서

1. 최종 사용처부터 적기

개발자가 읽기 쉬운 정의보다 앱이 실제로 사용할 결과를 먼저 적어 보세요. 예를 들면 category, urgent, summary, reference_date처럼 저장할 필드를 목록화합니다. 화면에 표시할 값과 내부 판단용 값을 같은 필드에 섞지 않는 것이 좋습니다.

2. 타입과 필수 여부 고정하기

  • 문자열·숫자·boolean·배열·객체 중 타입을 정합니다.
  • 항상 필요한 키와 상황별 선택 키를 나눕니다.
  • 값이 없을 때 빈 문자열, null, unknown 중 무엇을 쓸지 정합니다.
  • 날짜는 한 가지 형식과 시간대를 정하고 금액은 통화 코드를 분리합니다.

‘원문에 날짜가 없음’과 ‘모델이 날짜를 추출하지 못함’은 다른 상태입니다. 둘을 같은 빈 값으로 저장하면 나중에 사람이 검토해야 할 대상을 찾기 어렵습니다.

3. enum과 예외 상태 만들기

분류가 billing·technical·other로 제한된다면 허용값을 명시하세요. 그러나 실제 입력은 어느 범주에도 맞지 않을 수 있으므로 unknown이나 검토 대기 상태를 마련해야 합니다. 모든 입력을 억지로 기존 범주에 넣는 설계는 형식은 깨끗해 보여도 업무 데이터의 의미를 흐립니다.

4. 실패를 성공 객체와 분리하기

정상 응답, 안전 정책에 따른 거절, 지원하지 않는 Schema, 중단·시간 초과·네트워크 오류, 내용 검증 실패를 각각 다루세요. 거절 문장을 정상 객체의 summary에 넣어 저장하면 후속 시스템이 오류를 정상 문의로 오인할 수 있습니다. 공급자와 SDK마다 실패 응답의 모양이 다르므로 현재 공식 문서를 확인해야 합니다.[1][2]

파싱 뒤에 해야 할 검증

  1. 응답이 예상한 최상위 객체인지 확인합니다.
  2. 필수 키와 중첩 객체가 모두 있는지 검사합니다.
  3. 타입, enum, 문자열 길이, 배열 개수를 확인합니다.
  4. 날짜·금액·이메일·식별자를 업무 규칙으로 검증합니다.
  5. 추출값을 원문과 대조하고, 근거가 없으면 검토 대기로 보냅니다.
  6. 검증을 통과한 결과만 저장·발행·자동 실행합니다.
검사 층위 예시 통과하지 못했을 때
JSON 파싱 문법상 JSON인가 재시도 또는 오류 기록
Schema 필수 키와 타입이 맞는가 요청·모델 지원 범위 점검
업무 규칙 합계와 날짜가 원문과 맞는가 자동 저장하지 않고 사람 검토

재시도도 제한적으로 사용하세요. 키가 빠졌다면 Schema와 모델 지원 범위를 먼저 고치고, 원문과 내용이 다르면 같은 요청을 반복하기보다 근거 문장을 포함한 검토 흐름을 마련하는 편이 낫습니다. 네트워크 오류와 거절 응답은 같은 실패가 아니므로 상태를 구분해 기록하세요.

공급자 문서를 확인할 때

OpenAI와 Google 모두 구조화된 출력을 제공하지만, 지원 모델·중첩 구조·열거형·엄격 모드·거절 표시·SDK 설정은 같다고 가정할 수 없습니다.[1][2] 한 공급자의 예제를 다른 SDK에 그대로 옮기지 말고 현재 모델의 공식 예제와 실제 반환 객체를 기준으로 연결하세요. Schema가 복잡해지면 토큰, 지연, 비용, 유지보수 부담도 함께 살펴야 합니다.

적용 전 체크리스트

  • 사람이 읽는 문장인지 프로그램이 읽는 데이터인지 구분했나요?
  • 필수·선택 키와 null·unknown 정책을 정했나요?
  • 날짜·금액의 형식과 단위를 고정했나요?
  • 허용 목록 밖의 입력을 검토 대기로 보낼 수 있나요?
  • 거절·중단·네트워크 오류를 정상 결과와 나누나요?
  • 파싱·Schema·사실 검증을 별도 단계로 두었나요?
  • 실패 결과가 자동 발행이나 계정 변경으로 넘어가지 않나요?

자주 묻는 질문

구조화된 출력이면 AI가 틀리지 않나요?

아닙니다. 형식과 타입이 맞는 잘못된 날짜나 분류도 만들 수 있습니다. 원문 대조와 업무 규칙 검증이 필요합니다.

JSON mode와 구조화된 출력을 모두 써야 하나요?

아닙니다. 유효한 JSON이면 충분한지, 정해진 Schema까지 필요한지에 따라 선택하세요. 기능 이름과 지원 범위는 모델 문서에서 확인합니다.[1]

모든 모델이 같은 Schema를 지원하나요?

아닙니다. 공급자와 모델에 따라 타입·제약·오류 응답이 다를 수 있습니다.[1][2]

검증 실패를 무조건 재시도하면 되나요?

실패 원인을 먼저 분류하세요. 지원 문제·모호한 입력·원문 불일치·네트워크 장애마다 대응이 다르며, 정해진 횟수를 넘으면 사람 검토로 보내는 편이 안전합니다.

작은 업무로 먼저 검증하는 방법

처음부터 결제·발행·계정 변경에 연결하지 말고, 실패해도 되돌릴 수 있는 분류 업무로 시작하세요. 예를 들어 고객 문의 열 개를 넣고 category·urgent·summary가 모두 존재하는지, unknown이 필요한 입력을 억지로 분류하지 않는지 확인합니다. 정상 입력만 시험하지 말고 빈 문서, 긴 문장, 특수문자, 날짜가 없는 문서, 여러 언어가 섞인 문서도 포함하세요.

시험 입력 볼 결과 다음 조치
필드가 모두 있는 정상 문서 필수 키·타입·허용값 저장 전 검증 통과 여부 기록
날짜·금액이 없는 문서 null·unknown 정책 검토 대기로 분리
매우 긴 문서 잘림·중단·비용 입력 길이와 재시도 제한 설정
거절될 수 있는 입력 정상 객체와 오류 상태 구분 자동화 다음 단계로 보내지 않음

Schema를 바꿀 때는 기존 데이터와의 호환성도 살펴야 합니다. 필드 이름을 바꾸거나 필수 항목을 추가하면 예전 레코드를 읽는 코드가 실패할 수 있어요. 새 버전의 Schema를 별도 버전으로 기록하고, 변경 전후의 검증 결과를 비교하면 마이그레이션 대상을 찾기 쉽습니다.

운영 중 기록할 항목

  • 사용한 모델·Schema 버전과 요청 시각
  • 정상·거절·중단·검증 실패의 상태
  • 원문과 결과가 달라 사람이 수정한 필드
  • 재시도 횟수와 최종 처리 결과

이 기록은 모델이 항상 맞는지 증명하는 자료가 아니라, 어떤 유형에서 검토가 필요한지 찾는 운영 자료입니다. 오류가 반복되면 프롬프트만 길게 만들기보다 Schema·입력 범위·사람 승인 지점을 다시 설계하세요.

외부에 공개할 결과라면 검증 통과 여부와 사람이 수정한 부분을 함께 기록하세요. ‘Schema에 맞음’이라는 로그만 남기면 형식은 정상인데 사실이 틀린 결과를 나중에 구분하기 어렵습니다. 자동화의 마지막 단계에 승인 큐를 두는 것도 좋은 경계입니다.

검증 결과와 승인 여부를 함께 저장하면 운영자가 실패 원인을 빠르게 추적할 수 있습니다.

관련 글

Sources

  1. [1] OpenAI 개발자 문서, Structured model outputs
  2. [2] Google AI for Developers, 구조화된 출력

함께 읽을 글