API를 통해 모델의 출력을 JSON 형태로 받고, 이를 그대로 데이터베이스나 후속 처리 과정에 전달할 때 가장 문제가 되는 경우는 'HTTP 200이 반환되었지만 내용물이 사용 불가능한' 경우입니다. 본 메모에서는 claude-sonnet-5-5와 claude-opus-5-5를 동일한 조건으로 호출하여 구조화 출력(structured output) 작업에서 어떤 일이 발생했는지 정리합니다.
결론부터 말씀드리자면, 이번 테스트에서는 두 모델 모두 JSON 추출 작업을 모두 올바르게 처리했습니다. 차이가 나타난 부분은 정확도(accuracy)가 아니라 속도와 출력 길이였습니다. 다만, 긴 문서에서 특정 조건을 추출하는 작업의 경우, 두 모델 모두 '원래 대상이 아닌 항목'을 혼합하여 포함시키는 경우가 있었으므로, 후속 단계에서의 검증은 생략할 수 없습니다.
엔드포인트는 https://api.crazyrouter.com/v1의 /chat/completions이며, 모델 ID는 claude-sonnet-5-5와 claude-opus-5-5입니다. 테스트는 2026-11-09에 진행되었으며, 총 132회의 호출이 모두 HTTP 200을 반환했습니다. max_tokens는 4096으로 고정했으며, effort 파라미터는 지정하지 않고 인터페이스의 기본값을 사용했습니다.
구조화 출력과 관련된 작업은 다음 두 가지입니다.
- 주문 텍스트에서 JSON 추출: 주문 번호, 고객명, 상품 배열(array), 총 금액, 통화를 하나의 JSON 객체로 반환합니다.
- 로그 라인을 JSON Lines로 변환: 각 라인을
ts, level, module, msg 키를 가진 JSON으로 만듭니다.
두 작업 모두 정답이 하나로 결정되므로, JSON 파싱(parsing)과 필드별 값 대조를 통해 판정했습니다. 3회의 시도 모두에서 두 모델 모두 모든 필드가 일치하는 결과를 보였습니다.
또 다른 작업은 약 5,000~8,000자 분량의 요구사항 문서에서 강한 제약(상한선, 기한, 보존 기간 등)을 표 형태로 만드는 작업입니다. 이 문서에는 구 버전 수치나 아직 결정되지 않은 계획 항목과 같은 '대상 외 기술'이 의도적으로 포함되어 있습니다.
두 모델 모두 주요 제약 사항은 모두 추출했습니다. 하지만 Opus는 3회의 시도 중 1회에 걸쳐 표 안에 '대상 외' 항목을 혼합하여 넣었습니다. 예를 들어, Opus는 한 번의 시도에서 'CSV와 JSON 업로드 대응'이라는 기능 설명을 제약 조건으로 표에 추가했습니다. 해당 설명문 내에서는 '수치 제한이 아니다'라고 명시되어 있었지만, 이 표를 기계적으로 읽어 들일 경우, 이 행이 불필요한 제약 조건으로 처리될 위험이 있습니다.
Sonnet의 경우 이번에는 이러한 혼입은 확인되지 않았으나, 같은 형식의 출력을 다루는 이상 다음 두 가지 사항을 구현하는 것이 현실적입니다.
- 출력에 열(column)을 추가하여 각 행이 '수치 제약'인지 '기능 설명'인지를 구분하도록 합니다.
- 후속 단계에서 표의 각 행이 원문상의 수치와 일치하는지 기계적으로 확인합니다.
JSON을 받는 쪽에서는 다음 순서로 확인하면 문제 분리가 용이합니다.
finish_reason이 stop인지 확인합니다. length인 경우 JSON이 중간에 잘렸을 가능성이 있습니다.
- JSON으로 파싱 가능한지 확인합니다.
- 필수 필드가 갖춰져 있는지, 타입이 일치하는지 확인합니다.
- 값을 원문과 대조할 수 있다면 대조합니다.
이 중 1번과 2번은 모델에 관계없이 반드시 구현해야 합니다. 3번과 4번은 작업의 성격에 따라 결정됩니다.
이번 테스트에서는 속도와 출력 길이에 일관된 차이가 있었습니다. JSON 추출 같은 짧은 출력 작업에서도 Opus는 Sonnet보다 약간 더 길게 답변하는 경향을 보여 총 출력 토큰이 많아졌습니다. 구조화 출력만을 목적으로 한다면, 이 차이는 주로 비용과 지연 시간(latency)에 영향을 미치며 정확도에는 영향을 주지 않습니다.
수치는 동일한 연결 경로에서 얻은 것이므로 네트워크나 부하에 따라 달라질 수 있습니다. 참고용으로만 활용해 주십시오.
모델 ID가 자신의 계정에서 사용 가능한지는 Crazyrouter의 모델 목록에서 확인할 수 있습니다.
이번 구조화 출력 작업은 2종류, 각 3회입니다. 대상은 영어 주문 예시와 로그 형식에 한정되며, 일본어 양식이나 복잡한 중첩 구조는 포함하지 않았습니다. 모든 호출은 동일한 호환 게이트웨이를 거쳤습니다. 요금은 이번에 확인하지 않았습니다.
모델 선택을 고려한다면, 자신의 실제 입력으로 동일한 검증을 돌려보는 것이 확실합니다. 이때 usage와 finish_reason을 매번 기록해 두면 나중에 원인을 추적하기 쉽습니다.