본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 06. 05. 17:09

정규표현식의 지옥에서 LLM 함수 호출(Function Calling)까지: 나의 데이터 추출 여정

요약

다양한 서식의 PDF 송장에서 데이터를 추출하기 위해 정규표현식과 OCR 대신 LLM의 함수 호출(Function Calling) 기능을 활용한 사례를 다룹니다. 패턴 매칭의 한계를 극복하고 구조화된 JSON 데이터를 얻는 과정과 환각 현상을 제어하기 위한 검증 전략을 설명합니다.

핵심 포인트

  • 정규표현식과 템플릿 매칭은 비정형 문서 대응에 한계가 있음
  • LLM의 함수 호출을 통해 의미론적 데이터 추출 가능
  • LLM의 환각(Hallucination) 방지를 위한 사후 검증 필수
  • JSON 모드 및 구조화된 출력을 통한 데이터 신뢰성 확보

몇 달 전, 저는 제 커리어 선택을 의심하게 만든 문제에 직면했습니다.

저는 500개가 넘는 PDF 송장(Invoice)이 담긴 폴더를 뚫어지게 쳐다보고 있었습니다. 각 송장에는 송장 번호, 날짜, 품목(Line items), 합계와 같은 동일한 필드가 있었지만, 서식은 파일마다 제각각이었습니다. 어떤 것은 표(Table) 형태였고, 어떤 것은 열(Column) 형태였으며, 어떤 것은 단순히 대시(-) 구분자가 있는 텍스트 블록이었습니다. 클라이언트는 이 모든 데이터를 깔끔한 JSON 배열로 받기를 원했습니다.

처음에 저는 이렇게 생각했습니다. "정규표현식(Regex)을 쓰자. 패턴 몇 개를 작성하고 테스트하면 하루 만에 끝날 거야." 그것은 순진한 생각이었습니다.

시도했지만 실패했던 것들

1. 정규표현식(Regex) 기반 추출

문서의 80%에 작동하는 정규표현식을 작성하는 데 이틀을 보냈습니다. 나머지 20%에는 필드 누락, 추가 공백, 병합된 셀과 같은 예외 케이스(Edge cases)가 있었고, 이들이 모든 것을 망가뜨렸습니다. 하나의 예외 케이스를 수정할 때마다 다른 부분이 깨졌습니다. 결국 저는 유지보수가 불가능할 정도로 조건부 로직이 가득한 방대한 Python 스크립트를 갖게 되었습니다.

2. PyMuPDF를 이용한 템플릿 매칭

그다음에는 텍스트 위치를 추출하여 템플릿을 매칭하는 방식을 시도했습니다. 결과는 마찬가지였습니다. 글꼴, 정렬, 들여쓰기가 너무 많이 달랐습니다. 좌표를 하드코딩하는 방식은 실패할 수밖에 없었습니다.

3. Tesseract를 이용한 OCR

PDF가 스캔된 이미지인 경우, OCR(광학 문자 인식)은 오타나 잘못 인식된 문자 같은 노이즈를 한 층 더 추가했습니다. 데이터를 추출하는 시간보다 OCR 출력물을 정제하는 데 더 많은 시간을 보냈습니다.

일주일이 지난 후, 제가 가진 파이프라인은 매우 취약해졌고 거의 모든 송장에서 여전히 오류를 뱉어냈습니다. 저는 클라이언트에게 이것은 불가능하다고 말할 준비가 되어 있었습니다.

결국 성공했던 방법

그러다 단순히 요약뿐만 아니라, 함수 호출(Function calling)을 통해 실제 JSON 출력을 생성하는 구조화된 데이터 추출(Structured data extraction)에 LLM을 사용하는 방법에 대해 듣게 되었습니다. 저는 회의적이었습니다. LLM은 확률적(Probabilistic)인데, 어떻게 정확한 송장 번호를 신뢰성 있게 추출할 수 있단 말인가?

하지만 저는 작은 하위 집합(Subset)으로 시도해 보기로 했습니다. 저는 pdfplumber를 통해 추출한 각 PDF의 텍스트를 송장 스키마(Schema)에 대한 함수 호출 정의와 함께 OpenAI의 API로 보내는 Python 스크립트를 작성했습니다. 아이디어는 이랬습니다. 취약한 패턴으로 텍스트를 파싱하는 대신, LLM이 의미론(Semantics)을 이해하고 필드를 매핑하도록 하는 것입니다.

함수 호출 (Function Call)은 다음과 같은 모습이었습니다:

import json
import openai
import pdfplumber
...

저는 이를 20개의 송장 (Invoice)에 실행했습니다. 처음 10개는 완벽했습니다. 숫자도 일치했고, 날짜도 정확했으며, 수량이 누락된 까다로운 품목 (Line items)조차 null로 표시되었습니다. 저는 깜짝 놀랐습니다.

하지만 그다음 10개에서 문제가 발생했습니다. LLM이 공급업체 (Vendor) 이름을 환각 (Hallucination)하거나, 소수점을 잘못 읽었습니다. 그래서 저는 사후 처리 검증 (Post-processing validation)을 추가했습니다. 그리고 환각을 줄이기 위해 구조화된 출력 형식 (Structured output formats), 구체적으로는 JSON 모드 (JSON mode)나 제약된 디코딩 (Constrained decoding)에 대해 배웠습니다.

교훈 및 트레이드오프 (Trade-offs)

  • LLM은 마법 같은 정규표현식 (Regex)이 아닙니다. LLM은 결정론적 검증 (Deterministic validation)과 결합했을 때 가장 잘 작동합니다. 예를 들어, 추출 후 송장 번호가 INV-\d{6}와 같은 패턴과 일치하는지 확인하십시오. 일치하지 않으면 거부하고 재시도하십시오.
  • 비용이 중요합니다. GPT-4를 통해 PDF를 처리하는 데는 페이지당 약 $0.01~$0.05가 소요됩니다. 500개의 송장의 경우 $25~$125가 듭니다. 하지만 제 시간은 그보다 더 비쌉니다. 그만한 가치가 있었습니다.
  • 프롬프트 엔지니어링 (Prompt engineering)이 핵심입니다. 프롬프트에 추출 예시를 포함하는 것이 정확도를 15% 향상시킨다는 것을 발견했습니다.
  • 모델 선택 (Model selection). GPT-3.5는 더 빠르고 저렴했지만 품목 (Line items)에서 더 많은 실수를 했습니다. GPT-4는 프로덕션 (Production) 환경에 충분히 신뢰할 만했습니다.
  • 개인정보 보호 (Privacy). 데이터를 외부 API로 전송하게 됩니다. 민감한 송장의 경우, Ollama를 사용하여 로컬 모델 (Llama 3 또는 Mistral)을 사용할 것입니다. 속도는 더 느리지만 프라이버시가 보장됩니다.

프로토타입을 더 빠르게 만드는 데 도움이 된 도구 중 하나는 Interwest AI extraction platform이었습니다. 이 플랫폼은 기본적으로 이 패턴을 감싸고 있습니다. 템플릿을 업로드하고 필드를 정의하면 LLM 백엔드를 사용합니다. 하지만 중요한 것은 접근 방식입니다. 즉, 함수 호출 (Function calling)을 통한 의미론적 추출 (Semantic extraction)입니다.

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

  • 먼저 LLM 접근 방식을 사용하세요. 정규표현식(regex)에 며칠을 허비하지 마세요. 절약되는 개발 시간이 엄청납니다.
  • **Pydantic과 같은 스키마 검증 라이브러리 (schema validation library)**를 사용하여 LLM 출력을 파싱하세요. 이는 오류를 조기에 잡아냅니다.
  • 백오프 (backoff)를 포함한 재시도 (retries) 로직을 구현하세요. 만약 LLM이 유효하지 않은 JSON을 반환하면, 해당 오류를 피드백으로 다시 전송하세요.
  • 비용 최적화를 고려하세요. 대량의 추출 작업이 필요한 경우, 레이아웃별로 문서를 사전 분류하고 단순한 레이아웃에는 더 저렴한 모델을 사용하세요.

이 접근 방식을 사용하지 말아야 할 때

  • 완벽하게 일관된 문서가 아주 소수뿐이라면, 정규표현식 (regex)으로도 충분합니다.
  • 실시간 추출(예: 모바일 앱 상에서)이 필요한 경우, API 호출의 지연 시간 (latency)이 너무 높을 수 있습니다.
  • 데이터가 매우 민감하여 외부 API를 사용할 수 없는 경우, 로컬 모델 (local model)을 실행하세요.

결론

LLM 함수 호출 (function calling)은 거의 불가능에 가까웠던 작업을 주말 프로젝트 수준으로 바꾸어 놓았습니다. 이것이 만능 해결책 (silver bullet)은 아닙니다. 여전히 검증, 오류 처리, 그리고 명확한 스키마 (schema)가 필요합니다. 하지만 모든 예외 케이스 (edge case)에 대해 규칙을 작성하려고 시도하는 것보다는 훨씬 더 낫습니다.

엉망인 데이터를 추출하는 여러분만의 방식은 무엇인가요? 이 기술을 시도해 보셨나요, 아니면 더 전통적인 방식을 고수하시나요? 여러분에게 효과적이었던 방법이 무엇인지 듣고 싶습니다.

AI 자동 생성 콘텐츠

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

원문 바로가기
0

댓글

0