13.5.6 룩업(Lookup) 실패 시의 폴백(Fallback) 전략 및 예외 처리

13.5.6 룩업(Lookup) 실패 시의 폴백(Fallback) 전략 및 예외 처리

앞서 살펴본 13.5.1절부터 13.5.5절까지의 3단계 외부 지식 기반 검증 오라클(Ground Truth Lookup Oracle)들은 비정형 파이프라인에 세계관을 부여하는 궁극의 무결점 보증 수표다. 그러나 이 3단계 오라클은 파이프라인 내에서 스스로 모든 것을 결제하는 1, 2단계의 ‘닫힌 로직(Closed Logic)’ 구조를 벗어나, 파이프라인 밖의 거친 외부 환경(External Network, API, 마스터 RDBMS)과 극도로 강하게 결합(Tightly Coupled) 되는 본질적이고 치명적인 공학적 리스크를 동시에 떠안게 된다.

만약 외부 관공서 API의 정기 점검망에 걸려 503 TIMEOUT 에러가 터지거나, 사내 벤더 마스터 DB가 야간 배치 작업으로 인해 일시적으로 락(Lock)이 걸렸거나, 데이터센터 간의 BGP 라우팅 문제로 네트워크 단절 상황이 발생한다면 어떻게 될까? 오라클이 이 외부와 통신 불능 상태에 빠진다면, 앞선 그 수많은 AI 추론과 비전 디코딩 연산, 그리고 1,2단계 오라클의 노력을 통과하며 달려온 이 값비싼 트랜잭션 텐서는 파이프라인 중간에서 그대로 고립되어 마비(Deadlock) 되고 허무하게 증발할 위기에 처한다.

따라서 3단계 통신망 오라클은, 룩업(Lookup) 연산이 인프라적 요인으로 실패했을 경우 무작정 메모리에 ValueError를 던지고 아까운 트랜잭션을 소실(Drop) 시키는 대신, 가장 성숙하고 견고한 **‘폴백(Fallback) 라우팅 전략’**과 **‘우아한 성능 저하(Graceful Degradation)’**를 이끄는 리트라이(Retry) 비동기 큐 루프를 필수적으로 설계해야만 한다.

1. 멱등적(Idempotent) 상태 보존과 메시지 큐(Message Queue) 라우팅

단순한 일시적 네트워크 지연(Latency) 문제일 경우를 철저히 대비해, 오라클의 메모리 인스턴스 레이어 바깥에 지수 백오프(Exponential Backoff) 알고리즘을 적용한 이벤트 기반(Event-driven) 큐를 마련하여 생명줄을 이어준다.

import pika # RabbitMQ 등과 연동하는 AMQP 메시지 큐 브로커 클라이언트
import json

def route_failed_lookup_transaction(transaction_payload: dict, error_reason: str):
    """ 
    네트워크 인프라 장애나 관공서 서버 에러로 인해 3단계 외부 오라클 검증이 중단된 경우, 
    데이터를 메모리에서 영구 소실시키지 않고 지수 백오프 기반의 지연 큐(Delayed Queue)나 
    인간 전문가 큐(HITL Queue)로 안전하게 다중 라우팅(Routing)한다.
    """
    
    # [Case 1] 일시적 네트워크 인프라 장애 (HTTP 502, 503, 504 / Connection Timeout) 
    # -> AI가 뱉은 데이터의 잘못이 아니라 시스템의 잘못. 죽이지 않고 큐에 잠재워서 지연 처리.
    if "[인프라 장애]" in error_reason or "[네트워크 타임아웃]" in error_reason:
        
        # Pydantic 텐서가 상태로 지니고 다니던 재조회 시도 횟수(Retry Count) 까보기
        retry_count = transaction_payload.get("oracle_lookup_retry_count", 0)
        
        if retry_count < 3: # 예: 최대 3회(15분 소요)까지 인내심을 갖고 망 복구를 기다림
            transaction_payload["oracle_lookup_retry_count"] = retry_count + 1
            
            # RabbitMQ의 Delayed Exchange 플러그인을 등을 통해 
            # 5분(지수 백오프 처리) 뒤 다시 3단계 오라클 검증 시스템망으로 재투입 시도
            queue_name = "ORACLE_INFRA_RETRY_DELAY_QUEUE"
            _publish_to_message_broker(queue_name, transaction_payload)
            return "SCHEDULED_FOR_DELAYED_RETRY"
            
    # [Case 2] 재시도 횟수 완전 초과 또는 명백한 논리/리걸 환각 위반 (폐업자, 무효 PO 번호 확인됨)
    # -> 더 이상 물어볼 필요가 없는 "데이터 본연의 독성(Toxicity)". 영구 격리 요망.
    # 즉각 영구 격리망(Dead Letter Queue) 또는 인간 회계 심사원(HITL) 전용 큐로 이관.
    queue_name = "HUMAN_EXPERT_ACCOUNTING_REVIEW_QUEUE"
    
    # 인간이 직접 눈으로 보고 디버깅할 수 있도록 오라클이 판독한 에러 사유를 태깅
    transaction_payload["oracle_rejection_reason"] = error_reason 
    
    _publish_to_message_broker(queue_name, transaction_payload)
    return "ROUTED_TO_HITL_FOR_MANUAL_INSPECTION"
    
def _publish_to_message_broker(queue_name: str, payload: dict):
    # 실제 RabbitMQ나 AWS SQS 등에 페이로드를 영속화(Persistence) 하여 
    # 파이프라인의 전원이 내려가도 데이터가 증발하지 않도록 지켜내는 종단 로직 구현부
    pass

2. 오라클 시스템의 가용성(Availability)에 대한 철학적 결론

이 폴백 라우팅 코드는 단순해 보이지만, 최고 사양의 MLOps 아키텍처를 가르는 가장 중요한 철학 하나를 깔고 있다. 바로 **“AI 모델 프롬프트의 잘못(Data Invalidity)”**과 **“파이프라인 주변 물리 인프라의 잘못(System Unavailability)”**을 철저히 분리해서 다루어야 한다는 사상이다.

3단계 지식 기반 API 오라클 망이 연산에 실패했을 때, 이 실패가 LLM이 문서를 엉터리로 파싱 하거나 환각을 일으켜서 엉뚱한 값으로 DB를 타격해 발생한 **데이터 유효성 위반 에러(Data Validation Error)**인지, 아니면 국세청 서버가 죽어서 응답을 단순히 받지 못한 **시스템 가용성 무응답 에러(System Availability Error)**인지를 명확히 식별해 내는 능력. 그리고 이 둘의 운명을 각각 다른 큐(Queue)로 찢어내는 통제력.

이러한 체계적 안정망(Safety Net)과 논리적 폴백(Fallback) 시스템의 완벽한 융합 시나리오야말로, 이 책 13장 전체를 거대하게 관통해 온 ’비정형 데이터의 엄격한 구조적 추출과 무결성 수호’라는 대장정의 완벽한 기술적 피날레(Finale)가 된다.
이제 우리의 오라클 엔진은 그 어떤 AI의 교활한 악의적 환각(Hallucination) 데이터도 본선으로 통과시키지 않는 완벽하고 차가운 ’절대의 방패’이자, 동시에 주변망 서버 인프라의 마비 속에서도 절대 자신의 메모리에 담은 트랜잭션 수치 데이터를 소실시키지 않는 불사조(Phoenix)와 같은 영속적 엔진으로 영광스럽게 거듭난 것이다.