본문 바로가기
Q&A2026년 8월 3일1분 읽기

response_format json_object를 켰는데 값이 비거나 필드가 통째로 빠져서 옵니다

l
llm_bora
조회 630댓글 3

고객 문의 텍스트에서 이름/이메일/요청유형 같은 걸 뽑아서 JSON으로 받는 추출기를 만들고 있어요. response_format을 { "type": "json_object" }로 켜뒀습니다. 유효한 JSON이 오긴 하는데, 문제는 내용이에요.

가끔 {} 처럼 아예 빈 객체가 오거나, 있어야 할 필드가 통째로 빠진 채로 옵니다. 어떨 때는 값은 다 있는데 이상하게 마크다운 코드펜스로 감싸서 오기도 하고요. 프롬프트에는 필드 이름이랑 예시 출력까지 다 적어놨는데도 이럽니다.

// 기대
{"name": "홍길동", "email": "a@b.com", "type": "환불"}
// 가끔 이렇게 옴
{}

json_object 켜면 스키마대로 나오는 거 아니었나요? 후처리에서 매번 방어 코드를 덕지덕지 붙이고 있는데 근본적으로 뭘 잘못하고 있는 건지 알고 싶습니다.

댓글 3

김김영삼2개월 전
json_object 모드는 딱 하나만 보장해요. 출력이 파싱 가능한 유효 JSON이라는 것. 어떤 필드가 있어야 하는지, 타입이 뭔지는 전혀 강제 안 합니다. 그래서 {} 도 유효한 JSON이니 통과하는 거예요. 스키마 보장이라고 오해하기 딱 좋은 이름이죠.

필드 구조까지 강제하려면 json_object가 아니라 스키마 기반 구조화 출력(json_schema, strict)을 써야 합니다. required에 필드를 다 넣고 additionalProperties를 false로 잠그면, 그 필드들이 반드시 지정한 타입으로 채워져 나옵니다. 마크다운 펜스로 감싸는 것도 이 모드에선 안 생겨요.

그리고 {} 로 비어 오는 케이스 중 일부는 모델이 값을 못 찾아서가 아니라 출력이 max_tokens에 걸려 잘린 겁니다. 그때 stop_reason/finish_reason이 length인지 꼭 확인하세요. 이건 스키마로도 못 살리고 토큰을 올려야 합니다.

마지막으로 프롬프트에 예시 출력을 마크다운 블록으로 보여주면 모델이 그 펜스까지 따라 하는 경향이 있어요. 구조화 출력으로 넘어가면 그 지시 자체가 필요 없어지니 지우세요.
lllm_bora(guest)2개월 전
json_schema strict로 바꿨더니 빈 객체랑 펜스 문제는 없어졌어요. 근데 이번엔 다른 게 걸립니다. 어떤 필드는 문의에 따라 있을 수도 없을 수도 있는 선택 필드인데, strict에선 required에 다 넣으라고 하니 없는 경우엔 어떻게 처리해야 하나요? 지금은 빈 문자열로 채워 오는데 그게 실제 빈 값인지 없는 건지 구분이 안 됩니다.
김김영삼2개월 전
strict 모드는 required에 필드가 다 들어가야 하는 게 맞아서, 선택 필드를 빼는 방식으론 못 합니다. 대신 그 필드를 nullable로 만드세요. 타입을 단일 문자열이 아니라 ["string", "null"] 처럼 null을 허용하는 형태로 정의하고, required에는 그대로 포함시키는 거예요.

그러면 값이 없을 때 빈 문자열이 아니라 명시적으로 null이 옵니다. 후처리에서 null 체크로 없음/있음을 딱 구분할 수 있고요. 프롬프트에도 해당 정보가 없으면 그 필드는 null로 두라고 한 줄 박아주면 모델이 빈 문자열로 얼버무리는 걸 줄여줍니다. enum 같은 걸 섞을 땐 null 케이스를 enum에 넣지 말고 타입 레벨에서 nullable로 처리하는 게 깔끔해요.
Ctrl+Enter로 등록