6.5.1 Enum(열거형) 활용: Open-ended 텍스트를 확정적 카테고리(Deterministic Category)로 변환

6.5.1 Enum(열거형) 활용: Open-ended 텍스트를 확정적 카테고리(Deterministic Category)로 변환

정제되지 않은 더러운 자연어(Natural Language)를 차갑고 엄밀한 시스템의 언어(System Language)로 번역하는 오라클(Oracle) 파이프라인 아키텍처에서 가장 먼저 마주치게 되는 필수적인 기초 공학 과제는 바로 **‘분류(Classification)와 라우팅(Routing)’**이다.
사용자의 장황하고 파편화된 긴 발화(Utterance)의 숨은 의도를 정확히 파악하여, 방대한 백엔드 마이크로서비스 아키텍처(MSA) 내의 특정 분기(Branch) 로직이나 담당 API로 트래픽을 정확하게 라우팅하는 것은 현대 AI 기반 소프트웨어 인프라의 가장 뼈대가 되는 기본기다.

1. 개방형 문자열(Open-ended String) 스키마가 초래하는 비결정성(Nondeterminism)의 혼돈

만약 주니어 엔지니어가 의도 분류(Intent Classification)를 담당하는 프롬프트 스키마를 아래와 같이 한없이 관대하고 느슨하게 텍스트 타입으로 설계하여 배포했다고 가정해 보자.

{
  "properties": {
    "user_intent": {
      "type": "string",
      "description": "사용자의 발화 의도(Intent)를 짧게 요약해서 작성하라."
    }
  }
}

이 상태에서 화가 난 사용자가 챗봇에게 “아 짜증 나네, 당장 내 돈 돌려줘. 환불해 주세요“라고 말했을 때, 통제되지 않은 자유로운 영혼의 LLM은 매 틱(Tick)마다 완전히 다른 변덕스러운 문자열을 뱉어낼 것이다.
운이 좋으면 "환불", API 상태가 안 좋으면 영어로 "refund", 혹은 아주 친절하게 "환불 요청", 심지어는 "사용자가 결제 취소를 간절히 원하는 듯함"이라는 장황한 문장형 스키마를 동적으로 생성해 버린다.

결과적으로 이 스키마를 수신하는 백엔드 서버의 하드코딩된 switch-case 문이나 if (intent === "REFUND") 같은 엄격한 상태 조건문(Condition)은 완전히 무용지물이 되어 쓰레기 값(Garbage Value)을 렌더링하다가 장엄하게 크래시(Crash)를 일으킨다. 이 열어둔(Open-ended) 스키마 상태로는 애플리케이션의 어떠한 결정론적 유닛 테스트(Unit Test)도 통과시킬 수 없으며, 파이프라인의 오라클은 붉은색 ‘Fail’ 경고등만 무기력하게 깜빡일 뿐이다.

2. Enum 스키마를 통한 무자비한 수학적 라우팅 제어(Mathematical Routing Control)

이러한 공학적 교착 상태를 가장 우아하고 확실하게 해결하는 파이프라인 최고 효율의 스키마 명세(Specification) 패턴은, 바로 Enum(열거형) 타입을 사용하여 LLM의 토큰 생성 자유도 가능성을 사전에 하드코딩으로 정의된 단 N개의 불변 상수(Immutable Constants) 집합으로 완벽히 묶어버리고 가둬버리는 것이다.

2.1 [Pydantic과 Enum을 결합한 파이프라인 방어 모델 아키텍처]

from enum import Enum
from pydantic import BaseModel, Field

class IntentType(str, Enum):
    REFUND = "REFUND"                      # 결제 취소 및 환불 라우팅
    TECHNICAL_SUPPORT = "TECHNICAL_SUPPORT" # 기술적 장애 접수 라우팅
    BILLING = "BILLING"                    # 영수증 및 과금 문의 라우팅
    OTHER = "OTHER"                        # 기타 및 예외 처리 라우팅

class IntentExtraction(BaseModel):
    user_intent: IntentType = Field(
        description="사용자의 요구나 목적이 정확히 어느 카테고리에 속하는지 명확하게 분류하라."
    )

위와 같이 견고하게 작성된 Pydantic 방어 모델이 런타임에 JSON Schema로 직렬화되어 (예: "enum": ["REFUND", "TECHNICAL_SUPPORT", "BILLING", "OTHER"] 페이로드) LLM 텐서플로우에 전달되면, 최신 API 서버의 내부 컴파일러는 제약 트리(Constraint Context Free Grammar, CFG)를 렌더링하여 확률 엔진을 강제로 덮어씌운다.
이로 인해 모델은 사전에 정의된 저 딱 4가지 대문자 단어 토큰 외의 그 어떤 불필요한 공백이나 다른 문자열도 생성하지 못하도록 **생성 확률(Logits) 자체가 0%로 완벽하게 하드 마스킹(Hard Masking)**된다. 이제 데이터베이스와 백엔드 트래픽 시스템은 LLM의 출력을 100% 무조건적으로 신뢰할 수 있으며, 엄격하고 아름다운 switch-case 라우터 로직을 초당 1만 건씩 에러 없이 안정적으로 가동할 수 있게 된다.

3. 오라클 설계자의 핵심 아키텍처 팁: ’OTHER’의 전략적 배치 (Escape Hatch)

그러나 이런 초강력 Enum 스키마를 설계할 때 MLOps 엔지니어가 저지르는 가장 흔하고 치명적인 실수는, 오직 비즈니스 기획서 로직에 당장 필요한 ‘정상구간’ 카테고리들만 빽빽하게 정의해 놓고 만족하며 배포해 버리는 것이다.

만약 위 스키마 예시에서 OTHER (기타) 옵션이 누락되어 빠져 있다고 가정해 보자.
어느 날 지나가던 악의적인 사용자가 챗봇 시스템에게 “너 지금 무슨 색 바지 입고 있어?” 같은 성희롱적 농담이나 “약 싸게 팝니다 클릭” 같은 무의미한 스팸 문자를 던졌을 때, 시스템의 강제성 때문에 갇혀버린 LLM은 어떻게든 대답해야 한다는 압박감에 시달린다. 결국 LLM은 셋 중 그나마 가장 텍스트 벡터가 그럴싸해 보이는(실은 전혀 관계없는) TECHNICAL_SUPPORT를 어거지로 선택하여 백엔드로 넘겨버리는 끔찍한 **‘강제 편향 환각(Forced Bias Hallucination)’**을 시스템상에 일으키게 된다.

따라서 엄격한 제어의 분류형 Enum 엔진을 사용할 때는, 모르는 것을 모른다고 뱉어낼 수 있는 통풍구이자 **논리적 도피처(Escape Hatch)**를 반드시 아키텍처에 하나 이상 강제로 마련해 두어야만 평가 오라클 데이터의 진실성(Ground Truth Integrity)이 오염되지 않고 유지된다.

  • OTHER (사전에 정의된 분류 체계에 관련 없음)
  • UNKNOWN (사용자의 정보 부족이나 난해함으로 도저히 의도를 알 수 없음)
  • NOT_APPLICABLE (N/A, 현 태스크나 권한에서 해당 사항 없음)

결론적으로, 지능적인 Enum 스키마 캡슐화 패턴은 통제 불능의 늪과 같은 자연어의 난폭한 혼잡함을 차가운 백엔드 서버가 가장 좋아하는 명확한 이산 수학(Discrete Mathematics)의 영역으로 평정하며 멱살 잡고 끌어내리는, 데이터 오라클 설계의 가장 강력하고 우아하게 동작하는 첫 번째 관문(Gateway)이다.