structured output 을 우리는 언제 쓰고 언제 안 쓰는가
JSON 스키마 강제 출력이 항상 좋은 것은 아니다. 팀이 실제로 적용하면서 만든 판단 기준을 정리한다.
모델이 JSON 을 확실하게 반환하게 만드는 방법이 생기자, 처음엔 모든 곳에 적용하고 싶었다. 파싱 오류가 사라지고 후처리 코드가 단순해지니까. 그런데 실제로 쓰다 보면 structured output 이 오히려 방해가 되는 경우가 있다.
structured output 이 잘 맞는 경우
다운스트림 시스템이 특정 형태를 기대할 때. 모델 응답을 DB 에 저장하거나 다른 API 에 전달한다면, 스키마를 미리 고정하는 것이 코드 전체를 안정적으로 만든다. 파싱 실패로 인한 런타임 오류가 없어진다.
필드 존재 여부가 중요한 분기 로직에서. “이 응답에 action 필드가 있으면 실행하고 없으면 넘어가라”는 로직을 구현할 때, 스키마가 보장되면 조건 분기가 명확해진다. nullable 여부도 스키마로 선언할 수 있다.
배치 처리에서 응답 일관성이 필요할 때. 수백 건의 요청을 처리할 때 각 응답이 같은 구조를 가지면 집계와 분석이 쉬워진다.
structured output 이 안 맞는 경우
추론 과정이 응답 품질에 영향을 줄 때. 모델이 생각의 흐름을 자연어로 풀어낸 뒤 결론을 도출하는 방식이 더 정확한 결과를 내는 경우가 있다. 스키마를 강제하면 이 과정이 압축되거나 생략될 수 있다. 복잡한 추론이 필요한 작업에서는 자유 형식 출력 후 별도로 파싱하는 방식이 나을 때가 있다.
탐색적 작업에서. 어떤 필드가 필요한지 아직 모르는 단계라면 스키마를 고정하는 것이 오히려 유용한 정보를 잘라낼 수 있다. 프로토타이핑 초반에는 자유 형식으로 출력받고, 패턴이 보이면 그때 스키마를 정의하는 편이 낫다.
단순 텍스트 응답이 충분할 때. 사용자에게 직접 보여주는 자연어 답변을 JSON 으로 감쌀 이유가 없다. 불필요한 구조는 코드 복잡도를 올릴 뿐이다.
우리가 정착한 방식
프로젝트에서 structured output 도입을 검토할 때 먼저 두 가지를 묻는다.
- 이 출력을 읽는 코드가 있는가? (있다면 스키마 고려)
- 응답 품질이 추론 과정에 의존하는가? (그렇다면 신중히)
도입하기로 결정하면 스키마는 가능한 한 좁게 정의한다. 필요한 필드만 포함하고, 선택적 필드는 명시적으로 nullable 로 표시한다. 이후에 필드를 추가하는 것은 쉽지만, 필드를 제거하면 기존 코드에 영향을 줄 수 있기 때문이다.
structured output 은 도구다. 모든 LLM 호출에 적용해야 하는 기본값이 아니라, 이유가 있을 때 선택하는 것이 맞다.
— by slecs