6.5 결정론적 정답지를 위한 스키마 설계 패턴

6.5 결정론적 정답지를 위한 스키마 설계 패턴

대형 언어 모델(LLM)이 생성하는 JSON 객체는 그 자체로 소프트웨어 백엔드(Backend) 시스템과 통신하는 API 계약(Contract)이다. 이 계약이 파기되면, 즉 모델이 스키마를 무시하거나 임의의 키(Key)를 추가하는 순간, 후속 프로세스는 파싱 에러(Parsing Error)와 함께 붕괴한다.

결정론적 오라클을 구축하기 위해서는 LLM에게 단순히 “JSON으로 답해라“를 넘어, “어떤 구조적 이탈도 허용하지 않겠다“는 강력한 통제를 가하는 스키마(Schema) 설계가 선행되어야 한다. 본 절에서는 모델의 환각적 변형을 원천 차단하고 오라클이 수리적으로 파싱할 수 있는 완벽한 골든 데이터셋(Golden Dataset)을 구축하기 위한 핵심 스키마 설계 패턴을 다룬다.

1. 폐쇄형 스키마 (Closed Schema) 패턴

LLM의 고질적인 습관 중 하나는, 프롬프트에 제공되지 않은 정보를 자신이 임의로 생성하여 JSON의 새로운 key-value 쌍으로 덧붙이려는 특성(Hallucination-driven verbosity)이다.

이를 차단하기 위한 가장 중요한 패턴은 스키마 정의 시 확장을 금지하는 폐쇄형 스키마다.

  • 구현 방식: JSON Schema 사양에서 additionalProperties: false를 명시적으로 선언한다.
  • 오라클의 역할: 백엔드의 Pydantic이나 Zod 오라클은 모델이 age, name 이외에 address라는 임의의 필드를 추가하여 응답했을 때, 이를 경고(Warning)로 넘기지 않고 즉각적인 데이터 무결성 위반(Fail)으로 처리한다. 이 패턴은 다운스트림(Downstream) 애플리케이션으로 오염된 데이터가 흘러가는 것을 완벽하게 방어한다.

2. 열거형 타입(Enum) 기반의 상태 제한 패턴

자연어의 동의어 패턴은 결정론적 검증의 가장 큰 적이다. 예를 들어, 시스템이 “주문 상태“를 추출해야 할 때 모델이 Processing, In Progress, Working on it 등 무한한 동의어를 뱉어낸다면, 테스트 코드는 모든 경우의 수를 if-else문이나 정규식으로 처리해야 하는 오라클 부채(Oracle Debt)를 떠안게 된다.

  • 구현 방식: 문자열(String) 필드를 오픈 텍스트(Open text)로 열어두지 말고, 반드시 정해진 배열 내에서만 선택하도록 Enum 제약 조건을 건다. (예: {"type": "string", "enum": ["PENDING", "APPROVED", "REJECTED"]})
  • 효과: LLM은 Enum 스키마 안에서 로짓(Logit)이 제한된 단어들 중 하나만을 선택하게 된다. 이는 자연어의 무한한 공간을 3가지의 확정적 상태(State)로 압축해 주며, 오라클 검증 로직은 단 한 줄의 Assert(status == "APPROVED")로 극도로 단순화된다.

3. 체인 오브 소트(CoT) 임베딩 스키마 패턴

JSON 구조화 출력을 사용할 때 주의해야 할 점은, 모델이 깊게 생각할 겨를도 없이 결론(Final JSON)부터 출력하게 되면 오답률이 급증한다는 것이다. 따라서 스키마 자체에 모델의 논리 전개 과정을 담아낼 수 있는 임시 버퍼(Buffer) 필드를 설계해야 한다.

  • 스키마 구조:
    {
      "reasoning_steps": ["1단계 분석...", "2단계 분석..."],
      "confidence_score": 0.95,
      "final_decision": "APPROVED"
    }
    
- **오라클의 역할:** 여기서 오라클의 평가 대상이 되는 결정론적 정답은 오직 `final_decision` 하나다. `reasoning_steps` 필드는 모델의 추론 성능을 끌어올리기 위한 보조 장치일 뿐 검증 대상이 아니다. 하지만 모델에 문제가 생겼을 때, 개발자는 이 `reasoning_steps` 필드의 내용을 읽음으로써 모델이 왜 그런 오답을 냈는지 역추적(RCA)할 수 있는 훌륭한 디버깅 로그를 얻게 된다.

## 4.  명시적 Null (Explicit Null) 허용 패턴


비정형 문서에서 데이터를 추출할 때, 대상 정보가 원문에 아예 존재하지 않는 경우가 잦다. 이때 스키마가 필드 누락을 허용(`optional`)하면, 모델이 값을 못 찾은 것인지 아니면 출력을 실수로 빼먹은 것인지 오라클이 구분할 수 없다.

- **구현 방식:** 추출할 데이터가 없을 경우 필드를 누락시키는 것이 아니라, `null`이나 `Not_Found`라는 값을 명시적으로 반환하도록 강제한다. (예: `{"type": ["string", "null"]}`)
- **효과:** 오라클은 반환된 JSON의 키(Key) 개수가 항상 스키마에 정의된 개수와 동일(Length Match)함을 확정적으로 보장받는다.

정답지를 위한 스키마 설계는 곧 **"AI 모델의 자유도를 수학적으로 통제 가능한 영역까지 자르는(Pruning) 과정"**이다. 이 강력한 스키마 패턴들이 올바르게 적용되어야만, 비결정적인 텍스트 생성기가 예측 가능한 톱니바퀴를 굴려내는 결정론적 파이프라인의 일부로 편입될 수 있다.