13.3.2 정규표현식(Regex)을 이용한 포맷 강제 (이메일, 전화번호, 사업자등록번호)

13.3.2 정규표현식(Regex)을 이용한 포맷 강제 (이메일, 전화번호, 사업자등록번호)

이전 절에서 Pydanticint, float, str과 같은 기본 메모리 자료형 검증의 위력을 확인했지만, 그것만으로는 복잡한 비즈니스 로직을 완벽하게 방어할 수 없다.
특히 기업 간 트랜잭션에서 ‘이메일 주소’, ‘전화번호’, ‘사업자등록번호(Business Number)’ 등은 고유한 형태와 기호의 나열을 지닌 **‘문자열 속의 기계적 식별자’**다. 이것들은 어텐션이 흐트러진 LLM이 창조적 환각을 발생시키기 가장 쉬운 타겟 필드이자, 데이터베이스 저장 시 미세하게 포맷이 깨지기만 해도 하위 API 쿼리를 모조리 망가뜨려 치명적인 인프라 장애를 유발하는 숨겨진 뇌관이다.

만약 LLM이 사업자 등록 번호 필드에 123-45-67890 이라는 정확한 형태 대신, 읽기 쉽다고 판단하여 1234567890(하이픈 누락)으로 반환하거나 망상에 빠져 알 수 없음이라고 텍스트를 기입한다면 어떻게 될까? 단순한 Pydantic str 타입 검사는 무사히 통과해 버리고, 이 더러운 텍스트가 DB에 삽입되어 시스템이 침묵 속에 파단된다.
따라서 1단계 오라클 아키텍트는 고전적이고 원시적이지만 우리 우주에서 가장 폭력적이고 확실한 필터링 무기인 **정규 표현식(Regular Expression, Regex)**을 스키마 레벨에 하드코딩하여, 문자의 나열 순서부터 특수 기호의 강제 삽입 여부까지 마이크로 레벨로 통제(Format Enforcement)해야 한다.

1. 절대적 패턴 강제를 위한 Regex 오라클 설계

Pydantic의 Field(pattern="...") 또는 constr(regex="...") 제약 변수를 활용하면, 우리가 작성한 파이썬 정규식은 자동으로 JSON Schema의 pattern 속성으로 역컴파일되어 LLM 프롬프트에 ’출력 가이드’로 주입됨과 동시에, 백엔드의 엄격한 ‘런타임 검문소’ 역할을 양방향으로 완벽하게 수행한다.

from pydantic import BaseModel, Field

class VendorIdentityExtract(BaseModel):
    """ 정규식 오라클이 결합된 식별자 추출 강타입 객체 """
    
    # [1] 사업자등록번호: 반드시 XXX-XX-XXXXX 포맷으로만 출력을 강제함
    business_number: str = Field(
        ..., 
        # LLM이 하이픈을 빼먹으면 이 정규식 방어막을 뚫지 못하고 즉각 파단됨
        pattern=r"^\d{3}-\d{2}-\d{5}$",
        description="사업자 등록 번호 (무조건 XXX-XX-XXXXX 포맷이어야 함)"
    )
    
    # [2] 전화번호: 국제 표준 또는 일반적인 숫자와 기호의 조합만 허용
    phone_number: str = Field(
        ...,
        # 알파벳이나 "전화번호 불명" 같은 환각 문자열이 들어오는 즉시 요격
        pattern=r"^\+?[\d\s\-]{9,15}$",
        description="벤더 전화번호 유선/무선 번호"
    )

    # [3] 이메일: 표준 이메일 규격(RFC 5322 패턴) 기반 문자열 강제
    billing_email: str = Field(
        ..., 
        # ID@DOMAIN.TLD 구조가 아니면 무자비하게 차단
        pattern=r"^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$",
        description="송장 발송 담당 이메일"
    )

2. 정규식 오라클의 실패 피드백과 ‘자가 교정(Self-Correction)’

만약 LLM 에이전트가 이 타이트한 스키마 구조를 부여받고도 business_number 필드에 "1234567890" 이라는 하이픈 빠진 문자열을 생성했다면, Pydantic 런타임 컴파일러는 이 문자열을 보는 즉시 ValidationError: String should match pattern '^\d{3}-\d{2}-\d{5}$' 라는 기계적인 예외 로그를 사정없이 내뿜으며 시스템의 RDBMS 커밋을 원천 차단한다.

이 잔인하고 냉혹한 1단계 오라클 정규식 검사기의 진정한 위력은, 에러가 발생했을 때 이 “Regex 패턴 위반 익셉션 트레이스백” 자체를 그대로 다음번 재요청 프롬프트(Retry Error Feedback Prompt)에 실어서 LLM의 얼굴에 다시 집어던진다는 점에 있다.

LLM은 자신이 방금 확률적으로 생성해 낸 문자열이 백엔드의 어떤 수학적 정규식 로직(^\d{3}-\d{2}-\d{5}$)에서 격추당했는지 시스템으로부터 피드백을 전달받고, 어텐션을 수렴시켜 스스로 문자열 중간에 하이픈(-)을 강제 끼워 넣는 완벽한 **‘자가 교정(Self-Correction)’**을 수행하게 된다.
우리는 비결정론적이고 변덕스러운 지능에 우리의 운명을 기댄 것이 아니다. 우리는 결정론적 수학(Regex)으로 프레임을 짠 것이며, LLM은 이 정규식이라는 보이지 않는 감옥에 갇혀 오로지 완벽하게 정제되고 포맷팅된 데이터 토큰만을 토해내는 인프라 파이프라인의 안전한 노예로 전락하게 된 것이다.