13.3.3 Enum(열거형) 타입을 이용한 카테고리 데이터의 결정론적 매핑

13.3.3 Enum(열거형) 타입을 이용한 카테고리 데이터의 결정론적 매핑

비정형 문서 내에 존재하는 속성들 중 특정한 카테고리 속성(Categorical Data)들은, 거대 언어 모델(LLM) 특유의 유연하고 자유로운 어휘 선택권이 발휘될 때 시스템에 가장 큰 치명적인 재앙을 낳게 된다.

예를 들어 ’달러’라는 통화 단위 하나만 원본에서 추출하려 해도, LLM은 그날의 컨텍스트 윈도우(Context Window)나 프롬프트의 확률적 기분에 따라 USD, $, US Dollars, 미화, 심지어 미국 돈 등 무한대에 가까운 동의어 어휘 변형(Synonym Hallucination)들을 쏟아낸다. 당연하게도 엔터프라이즈 백엔드 시스템(ERP DB)은 이런 잡동사니 자연어 문자열을 알아듣고 파싱할 융통성도 없으며, 시스템 보안상 그런 유연성을 시스템 내부로 허용해서도 절대 안 된다.

만약 우리 백엔드 시스템의 데이터베이스 스키마가 허용하는 카테고리 값이 오직 몇 개의 허가된 **‘닫힌 집합(Closed Set)’**뿐이라면, 1단계 오라클 설계자의 최고 방어 전략은 LLM으로부터 모든 언어적 자유도를 물리적으로 빼앗아 버리고, 무조건 사전에 우리가 하드코딩으로 정의해 둔 ‘Enum(열거형) 타입’ 풀(Pool) 안에서만 응답을 강제 선택하도록 매핑(Mapping) 시키는 것이다.

1. 프롬프트의 구걸을 넘어서는 스키마의 족쇄 (Enum Enforcement)

프롬프트 엔지니어링 단계에서 시스템 프롬프트에 “부탁인데 통화는 제발 USD 또는 KRW 중 하나로만 추출해 줘” 라고 백 번 애원하는 것보다, Pydantic 강타입 모델에 파이썬 네이티브 Enum 메타 클래스를 족쇄처럼 박아 넣는 단 한 줄의 코드가 수천 배 더 강력하며 대수학적으로 절대적인 방어력을 지닌다.

from enum import Enum
from pydantic import BaseModel, Field, ValidationError

class CurrencyEnum(str, Enum):
    """ 백엔드 ERP 시스템이 허용하는 절대적인 통화 코드의 닫힌 집합 """
    USD = "USD"
    KRW = "KRW"
    EUR = "EUR"
    JPY = "JPY"

class DocumentPolymorphismEnum(str, Enum):
    """ 비정형 문서의 다형성을 결정론적인 4가지 팩토리 타입으로 묶어버리는 집합 """
    INVOICE = "INVOICE"
    RECEIPT = "RECEIPT"
    PURCHASE_ORDER = "PURCHASE_ORDER"
    QUOTE = "QUOTE"

class CategoricalDataExtractOracle(BaseModel):
    # Enum 클래스를 필드 타입으로 지정하면, Pydantic은 LLM용 JSON Schema를 렌더링할 때
    # 스스로 이 필드를 {"enum": ["USD", "KRW", "EUR", "JPY"]} 로 변환하여 주입한다!
    currency: CurrencyEnum = Field(
        ..., 
        description="문서의 결제 통화 (반드시 지정된 코드 중 하나여야만 함)"
    )
    # LLM 자체가 이 Enum 속성 중 하나를 스스로 선택해야만 하는 분류 게임 강제
    document_type: DocumentPolymorphismEnum = Field(...)

# [시뮬레이션] LLM이 '미국 달러'라는 Enum에 존재하지 않는 환각 문자열을 생성하여 반환했을 경우
try:
    data = CategoricalDataExtractOracle(
        currency="미국 달러",  # 환각 발생 지점
        document_type="INVOICE"
    )
except ValidationError as e:
    print("[오라클 요격 성공] Enum 닫힌 집합 위반 익셉션 격발!")
    # Pydantic 출력: 
    # 1 validation error for CategoricalDataExtractOracle
    # currency -> Input should be 'USD', 'KRW', 'EUR' or 'JPY'

2. Enum 강제의 부수적인 거대한 아키텍처 승리: 분류(Classification) 태스크의 흡수

Enum의 적극적인 시스템 도입은 단순히 변수 안에 들어온 텍스트가 맞는지 아닌지를 검증하는 소극적 오라클의 역할을 넘어선다. 이것은 파이프라인의 MLOps 아키텍처 그 자체를 최적화하는 엄청난 부수 효과(Side-effect)를 낳는다.

13.2.1절에서 우리는 현재 파이프라인으로 폭격처럼 쏟아져 들어오는 4가지 종류의 혼재된 문서 타입(인보이스, 영수증 등)을 알맞게 ‘분류(Classification)’ 해야 하는 과제가 있다고 언급했다.
과거의 전통적인 머신러닝 파이프라인 아키텍처에서는, 이 문서 분류를 처리하기 위해 별도의 BERT 기반 텍스트 분류기(Text Classifier) 서버를 마이크로서비스로 띄워 시스템 파이프라인 레이어(Layer)와 네트워크 I/O 병목을 하나 더 늘려야만 했다.

그러나 1단계 Pydantic 오라클 최상단에 DocumentPolymorphismEnum이라는 객체를 뼈대로 박아 넣는 순간, 기적이 일어난다.
우리는 별도의 분류 서버를 띄울 필요 없이, LLM 에이전트가 단 한 번 비싼 인퍼런스(Inference)를 태워 문서에서 데이터를 **‘추출(Extraction)’**하는 그 동일한 트랜잭션 라운드 안에서, 동시에 문서가 4가지 중 어떤 타입의 거푸집에 들어맞는지 **‘분류(Classification)’**하는 라우팅 태스크까지, 강타입 Enum을 매개체로 완벽하게 흡수하여 동시에 끝내버릴 수 있게 된 것이다.

이처럼 Enum(열거형) 은 LLM의 무한한 언어적 불확실성을 유한한 닫힌 집합(Closed Set)의 감옥으로 가두고, 애플리케이션의 런타임을 폭발적인 환각 메모리 침범으로부터 수호하는 가장 직관적이고 저렴하며 폭력적인 1단계 오라클 도구임을 명심해야 한다.
비정형 텍스트의 혼돈 세상에서 유일하게 확정적인 진리는, 오직 우리 시스템이 허락하고 미리 정의해 둔 ’열거된 카탈로그(Enum)’뿐이다.