Claude Vision API를 활용한 금융 문서 OCR 구축: 프로덕션 환경에서의 교훈
요약
Claude Vision API를 활용하여 복잡한 금융 문서(은행 명세서, 송장 등)를 구조화된 JSON 데이터로 변환하는 OCR 구축 방법을 다룹니다. 전통적인 OCR의 한계를 극복하고 프로덕션 환경에서 직면하는 이미지 품질 및 다중 페이지 처리 문제를 해결하는 실무적인 가이드를 제공합니다.
핵심 포인트
- Claude Vision은 문서의 시각적 구조를 이해하여 정규 표현식 없이 JSON 추출 가능
- 전통적 OCR의 한계인 암시적 테이블 구조와 숫자 오독 문제 해결
- 이미지 전처리를 통해 저품질 스캔 이미지의 정확도를 78%에서 94%로 향상
- 토큰 제한 및 비용 최적화를 위해 다중 페이지 처리 전략 수립 필요
Claude Vision API를 통해 수천 개의 은행 명세서(bank statements), 송장(invoices), 영수증(receipts)을 처리하면서, 금융 문서 OCR이 보기보다 훨씬 어렵다는 것을 배웠습니다. 실제 프로덕션 환경에서 무엇이 효과적인지 소개합니다.
문제점: 왜 전통적인 OCR은 금융 문서에서 실패하는가
Tesseract나 AWS Textract와 같은 전통적인 OCR 도구들이 금융 문서에서 어려움을 겪는 데에는 세 가지 이유가 있습니다:
- 테이블 구조가 암시적임 (Table structure is implicit) — 은행은 HTML 테이블을 사용하지 않습니다. 열(column)이 공백으로 구분되어 있어, 한 열이 어디서 끝나고 다음 열이 어디서 시작되는지 파악하기 어렵습니다.
- 숫자는 완벽해야 함 —
1을l로, 또는0을O로 혼동하면 회계 오류가 발생합니다. 단 하나의 숫자 오독만으로도 복식부기 (double-entry bookkeeping)가 깨질 수 있습니다. - 포맷의 혼란 (Format chaos) — 모든 은행은 서로 다른 레이아웃을 사용합니다. Chase의 명세서는 Wells Fargo의 명세서와 전혀 다르게 생겼습니다.
전통적인 OCR은 가공되지 않은 텍스트(raw text)를 제공할 뿐입니다. 이를 구조화된 데이터로 파싱하기 위해 여전히 수백 줄의 정규 표현식 (regex)을 작성해야 합니다.
Claude Vision API가 게임의 판도를 바꾸는 이유
Claude Vision은 단순히 텍ast를 추출하는 것이 아니라, 문서 구조를 이해합니다. 이미지와 함께 다음과 같은 프롬프트 (prompt)를 제공하면 됩니다:
"이 은행 명세서를 거래 날짜(transaction date), 내역(description), 차변(debit), 대변(credit), 잔액(balance) 열을 포함한 JSON으로 추출하세요."
Claude는 구조화된 JSON을 직접 반환합니다. 정규 표현식도, 수동적인 열 탐지(column detection)도 필요 없습니다.
실제 예시
입력: 은행 명세서 PDF (PNG로 변환됨)
프롬프트:
이 은행 명세서에서 모든 거래를 추출하세요. 다음을 포함한 JSON을 반환하세요:
- header: {accountNumber, statementPeriod, bankName}
- transactions: [{date, description, debit, credit, balance}]
...
출력:
{
"header": {
"accountNumber": "****1234",
...
파싱 코드도, 정규 표현식도 필요 없습니다. 데이터베이스에 바로 사용할 수 있는 구조화된 데이터가 준비될 뿐입니다.
프로덕션 과제 및 해결책
과제 1: 저품질 스캔
문제: 사용자들이 흐릿하거나, 기울어지거나, 조명이 좋지 않은 명세서 사진을 휴대폰으로 찍어 업로드합니다.
해결책: Claude로 보내기 전에 이미지를 전처리(preprocess)합니다:
from PIL import Image, ImageEnhance
def preprocess_image(img_path):
...
결과 (Result): 모바일로 촬영된 명세서의 정확도(Accuracy)가 78%에서 94%로 향상되었습니다.
도전 과제 2: 다중 페이지 명세서 (Multi-Page Statements)
문제 (Problem): 명세서는 5~10페이지에 달할 수 있습니다. 모든 페이지를 하나의 요청(request)으로 보내면 다음과 같은 문제가 발생합니다:
- 토큰 제한(token limits)에 걸림
- 지연 시간(latency) 증가
- 비용 증가
해결책 (Solution): 대부분의 사용 사례에서는 첫 페이지와 마지막 페이지만 처리합니다:
- 첫 페이지: 계좌 정보, 명세서 기간, 기초 잔액(opening balance)
- 마지막 페이지: 기말 잔액(closing balance), 요약(summary)
전체 거래 내역(transaction history)이 필요한 경우, 중간 페이지들을 배치 처리(batch-process)한 후 결과를 병합합니다.
import anthropic
def extract_statement_summary(pdf_pages):
...
비용 절감 (Cost savings): 명세서당 $0.15 → 명세서당 $0.03 (5배 감소)
도전 과제 3: 소수점 오류 (Decimal Point Errors)
문제 (Problem): Claude가 가끔 1,234.56을 123456 또는 12.34로 잘못 읽는 경우가 있습니다.
해결책 (Solution): 프롬프트(prompt)에 검증 규칙(validation rules)을 추가합니다:
금액 추출을 위한 규칙 (Rules for amount extraction):
1. 모든 금액은 반드시 소수점 둘째 자리까지 포함해야 함
2. "1,234.56"이 보이면, 1234.56으로 추출할 것
...
또한 코드에서 검증합니다:
def validate_amount(amount):
if amount is None:
return None
...
결과 (Result): 소수점 오류가 3.2%에서 0.4%로 감소했습니다.
도전 과제 4: 모델 폴백 (Model Fallback)
문제 (Problem): 피크 시간대에는 Claude Sonnet 4에 대한 속도 제한(rate-limits)이 가끔 발생합니다.
해결책 (Solution): 모델 폴백(model fallback)을 구현합니다:
MODELS = [
"claude-sonnet-4-20250514", # 기본 모델 (Primary)
"claude-3-5-sonnet-20241022", # 폴백 모델 (Fallback)
...
결과 (Result): 피크 사용 시간대에도 99.7%의 가동 시간(uptime)을 유지했습니다.
도전 과제 5: 예외 케이스 처리 (Handling Edge Cases)
문제 (Problem): 실제 명세서는 다음과 같이 특이한 형식을 가집니다:
- 페이지를 가로질러 나누어진 거래 내역 (Split transactions)
- 마이너스 잔액이
-1234.56대신(1234.56)으로 표시됨 - 날짜 누락 (예: 보류 중인 거래)
해결책 (Solution): 프롬프트에 예외 케이스(edge case) 처리를 명시합니다:
예외 케이스 (Edge cases):
- "(123.45)"와 같이 괄호 안에 있는 금액은 음수(debit)를 의미함
- 거래 내역에 날짜가 없는 경우, 명세서 종료일을 사용함
...
그리고 코드로 후처리(post-process)합니다:
def normalize_transaction(txn):
# 괄호를 음수로 변환
if txn['debit'] and '(' in str(txn['debit']):
...
비용 최적화 (Cost Optimization)
금융 문서 OCR은 비용이 많이 들 수 있습니다. 우리가 배운 점은 다음과 같습니다:
| 최적화 방법 | 비용 영향 | 정확도 영향 |
|---|---|---|
| 첫 페이지와 마지막 페이지만 처리 | -80% | -5% (요약용으로는 허용 가능한 수준) |
| ... | ||
| 현재 비용: 이 설정을 사용할 경우 은행 명세서당 $0.03, 영수증당 $0.01이 소요됩니다. |
프로덕션 환경에서의 정확도 지표 (Accuracy Metrics)
10,000개 이상의 문서를 처리한 후의 결과입니다:
| 문서 유형 | 정확도 | 비고 |
|---|---|---|
| 디지털 은행 명세서 (PDF) | 98.2% | 높은 대비, 깔끔한 레이아웃 |
| ... | ||
| "정확도(Accuracy)" = 추출된 데이터가 수동 검토 결과와 일치하는 정도를 의미합니다. |
Claude Vision을 사용하지 말아야 할 때
Claude Vision은 다음과 같은 경우에 완벽하지 않습니다:
- 수기 문서 (Handwritten documents) — 정확도가 70-80%로 떨어집니다.
- 실시간 처리 (Real-time processing) — 페이지당 지연 시간(Latency)이 2-4초입니다 (POS 시스템에는 너무 느림).
- 고보안 환경 (High-security contexts) — 데이터가 귀하의 인프라를 벗어납니다 (단, Anthropic은 API 데이터를 학습에 사용하지 않습니다).
이러한 경우에는 AWS Textract + 커스텀 파싱(custom parsing) 또는 온프레미스(on-premise) OCR을 고려하십시오.
핵심 요약 (Key Takeaways)
- 전처리(Preprocessing)가 중요합니다 — 대비 향상(Contrast enhancement) 및 그레이스케일 변환(Grayscale conversion)은 정확도를 10-15% 향상시킵니다.
- 모든 것을 검증하십시오 — 가공되지 않은 OCR 출력값을 절대 신뢰하지 마십시오. 소수점, 날짜 형식, Null 처리 등을 확인해야 합니다.
- 명시적인 프롬프트(Explicit prompts)가 승리합니다 — 규칙을 더 많이 지정할수록 프로덕션 환경에서의 예기치 못한 상황이 줄어듭니다.
- 공격적으로 비용을 최적화하십시오 — 대부분의 사용 사례에서 전체 페이지를 처리하는 것은 과합니다.
- 모델 폴백(Model fallback)은 필수입니다 — 속도 제한(Rate limits)은 발생할 수 있습니다. 백업 모델을 준비해 두십시오.
직접 시도해 보세요
본인의 명세서로 Claude Vision을 테스트해보고 싶으신가요? 위에서 언급한 기술들을 사용하여 은행 명세서를 Excel/CSV로 변환해주는 무료 도구인 CleanStmt를 제작했습니다.
전처리 파이프라인 소스 코드: GitHub (곧 공개 예정)
금융 문서 OCR에 대한 여러분의 경험은 어떠신가요? 비슷한 문제에 직면했거나 더 나은 해결책을 찾았다면 댓글로 남겨주세요.
ai #ocr #claude #fintech #python
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기