본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 06. 24. 10:29

데이터 추출에 Regex가 실패했던 경험과 현재 제가 사용하는 방법

요약

정규표현식(Regex)의 한계를 극복하기 위해 LLM의 함수 호출(Function Calling) 기능을 활용하여 비정형 데이터에서 구조화된 데이터를 추출하는 실용적인 방법을 소개합니다. Pydantic과 OpenAI API를 결합하여 데이터 형식 변화에 유연하게 대응하는 워크플로우를 제안합니다.

핵심 포인트

  • Regex는 비정형 데이터의 형식 변화에 매우 취약함
  • LLM의 Function Calling을 사용하면 스키마 기반의 JSON 추출 가능
  • Pydantic 모델을 정의하여 데이터 구조를 엄격하게 관리 가능
  • 입력 형식이 가변적인 저/중규모 데이터 추출 작업에 매우 효과적

지난달, 저는 공급업체의 PDF 인보이스에서 제품명과 가격을 파싱하기 위해 하루 종일 regex 패턴을 만들었습니다. 완벽하게 작동했지만, 다음 인보이스가 날짜 형식이 약간 다르고 콜론(:)이 빠져 있는 것을 받자 모든 것이 망가졌습니다. 마치 시시포스가 바위를 언덕 위로 밀어 올리는 기분이었습니다.

만약 여러분이 지저분하고 비정형적인 텍스트(PDF, 이메일, 웹 페이지)에서 구조화된 데이터를 추출하려고 시도해 본 적이 있다면 그 고통을 알 것입니다. 형식이 바뀝니다. 약어는 다양합니다. 그리고 여러분의 아름다운 regex는 취약한 괴물로 변합니다.

저는 다른 접근 방식들도 시도했습니다:

  • spaCy NER: 일반적인 개체명(entity) 추출에는 훌륭했지만, 제가 필요한 특정 필드에 대한 맞춤형 모델을 학습시키려면 제가 가지고 있지 않은 수백 개의 레이블링된 예시가 필요했습니다.
  • 템플릿 기반 추출 (Template-based extraction): 입력이 완벽하게 표준화되었을 때만 작동했고—그것은 결코 없었습니다.
  • 수동 복사/붙여넣기: 제가 가장 싫어하는 종류의 기술 부채였습니다.

그러다가 제 작업 흐름을 바꾼 무언가를 발견했습니다. 바로 구조화된 출력을 가진 대규모 언어 모델(LLMs) 사용—구체적으로 함수 호출(function calling) 또는 도구 사용(tool use) API를 이용하는 방식이었습니다.

기술: LLM 기반 구조화 추출 (LLM-Based Structured Extraction)

아이디어는 간단합니다. 원하는 데이터의 형태(스키마, schema)를 정의하고, 지저분한 텍스트를 LLM에 전달한 다음, 그 스키마와 일치하는 필드를 추출하도록 요청하는 것입니다. 모델은 JSON을 출력하며, 이 JSON은 여러분의 Python 스크립트나 데이터베이스에 직접 가져올 수 있습니다.

이것은 어떤 이론적인 'AI가 모든 것을 고칠 것'이라는 과장이 아닙니다. 이것은 제가 현재 낮은 볼륨(low-volume)이지만 높은 변동성(high-variance)을 가진 데이터 추출 작업에서 프로덕션 환경에 사용하는 실용적인 패턴입니다.

여기에 구체적인 예시를 소개합니다. 저는 다음과 같은 고객 이메일에서 주문 세부 정보를 추출해야 했습니다:

Hi, please confirm order #ABC123: 3x blue widgets at $12.50 each, 1x premium gadget (discounted) at $99.99. Shipping to 123 Main St, Springfield.

저는 예상되는 구조를 위해 Pydantic 모델을 정의했습니다:

from pydantic import BaseModel
from typing import List, Optional

...

그다음 저는 OpenAI의 함수 호출 (function calling) 기능을 사용하여 데이터를 채웠습니다. 핵심은 모델에게 어떤 필드가 기대되는지 정확히 알려주는 tools 파라미터였습니다.

import openai
import json

...

이제 extract_order_details("Hi, please confirm order #ABC123...")를 실행하면, 깔끔한 Python 객체를 돌려받습니다:

OrderExtraction(
    order_number='ABC123',
    items=[
...

정규표현식 (Regex)도, 취약한 패턴도 필요 없습니다. 내일 이메일 형식이 바뀌더라도, 제가 코드 한 줄 건드리지 않아도 LLM은 보통 스스로 적응합니다.

이 접근 방식이 빛을 발하는 경우

  • 입력 형식의 높은 가변성: 서로 다른 회사의 인보이스(Invoices), 다양한 인간의 문체가 담긴 이메일 등.
  • 소규모에서 중규모의 볼륨: 저는 하루에 수백 개의 문서를 처리합니다. 심각한 비용 고려 없이는 수백만 건 규모로 확장하기 어렵습니다.
  • 빠른 반복 (Iteration)이 필요한 경우: 스키마 (Schema)를 변경하는 작업은 Pydantic 클래스를 업데이트하고 다시 실행하는 것만큼 간단합니다.

한계점

이 방법이 만능 해결책 (silver bullet)인 척하지는 않겠습니다. 제가 발견한 트레이드오프 (trade-offs)는 다음과 같습니다:

  • 비용 (Cost): 각 API 호출에는 비용이 발생합니다. 처리량이 많은 파이프라인 (pipelines)에서는 이 비용이 빠르게 누적됩니다. gpt-4o-mini와 같은 더 저렴한 모델을 사용하는 것이 도움이 되지만, 여전히 공짜는 아닙니다.
  • 지연 시간 (Latency): 추출당 1~3초 정도를 예상해야 합니다. 실시간 애플리케이션은 이를 허용하지 못할 수도 있습니다.
  • 환각 (Hallucinations): 명시적으로 지정하지 않으면 모델이 때때로 필드를 지어냅니다. 그래서 저는 자유 형식의 채팅 대신 함수 호출을 강제하기 위해 항상 tool_choice를 사용합니다.
  • 결정론적 특성 (Determinism): 재시도 시 약간씩 다른 출력이 나올 수 있습니다. 저는 결과를 캐싱 (caching)하고 중요한 필드에 대해서는 인간의 검토 단계를 추가함으로써 이를 처리합니다.
  • 개인정보 보호 (Privacy): 외부 API로 데이터를 전송하는 것은 컴플라이언스 (compliance)를 위반할 수 있습니다. 그런 경우에는 (도구 호출을 지원하는 Llama 3와 같은) 자체 호스팅 모델이 필요합니다.

또한, 단순하고 잘 구조화된 입력(일관된 CSV 등)의 경우에는 여전히 정규표현식이 더 빠르고 저렴하다는 것을 발견했습니다. 고정된 컬럼을 가진 로그 파일을 파싱하는 데 LLM을 사용하지 마세요.

다음에 다시 한다면 다르게 할 점

만약 제가 처음부터 다시 시작한다면, 저는:

  1. 모든 추출 시도를 로그로 기록 (Log every extraction attempt) 하세요. 입력값, 출력값, 그리고 사용된 모델을 함께 기록해야 합니다. 이는 모델이 오작동할 때 디버깅하는 데 도움이 됩니다.
  2. 폴백 스키마 (fallback schema)를 정의하세요. Optional 필드를 사용하여 데이터가 누락되더라도 파이프라인이 중단되지 않도록 해야 합니다.
  3. 처리량이 설정 비용을 정당화할 만큼 많다면, 먼저 **로컬 모델 (local model)**을 사용하세요. Ollama + 함수 호출 (function calling) 기능은 매달 점점 더 좋아지고 있습니다.

참고로, 이 파이프라인을 구축하는 동안 정확히 이 패턴을 간단한 API로 래핑(wrap)한 서비스를 발견했습니다: https://ai.interwestinfo.com/. 아직 완전히 이전하지는 않았지만, 인프라 구축 작업을 건너뛰고 싶다면 살펴볼 가치가 있습니다.

진짜 교훈

최고의 도구가 항상 가장 복잡한 도구인 것은 아닙니다. 정규 표현식 (Regex)은 잘 정의된 패턴에 매우 훌륭합니다. 템플릿 파서 (Template parsers)는 구조가 고정되어 있을 때 잘 작동합니다. 하지만 인간이 생성한 데이터의 혼란스러운 엉망진창인 상황을 다룰 때는, 호출당 몇 센트의 비용을 지불하더라도 LLM이 힘든 일을 처리하게 하는 것이 여러분의 정신 건강을 지켜줄 수 있습니다.

자, 궁금합니다. 여러분은 지저분한 텍스트에서 구조화된 데이터를 추출할 때 주로 어떤 방법을 사용하시나요? 여전히 정규 표현식 (regex)을 고수하시나요, 아니면 AI라는 '어둠의 진영'으로 넘어오셨나요? 댓글로 알려주세요.

AI 자동 생성 콘텐츠

본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0