# 복잡한 재무 PDF를 JSON으로 변환하는 완벽 가이드 (초보자도 쉽게 따라 할 수 있는 단계별 방법)

---

# # 📌 서론 – “재무 보고서의 데이터, 왜 이렇게 어려울까?”

기업의 분기별 재무 보고서는 투자 판단, 회계 감사, 데이터 분석 등 다양한 비즈니스 의사결정에 필수적인 원천 자료입니다. 하지만 대부분 PDF 형태로 제공되기 때문에 **구조화된 데이터(표, 그래프, 텍스트)를 바로 활용하기가 어렵**습니다.

특히 10~20 페이지에 걸친 복잡한 표와 다중 레이아웃을 가진 재무 보고서는 자동화된 추출이 거의 불가능에 가깝다고 느껴지곤 합니다.

이 글에서는 **“PDF to JSON 변환”**이라는 핵심 목표를 두고, **“재무 보고서 데이터 추출”**을 파이썬 기반으로 구현하는 방법을 초보자도 이해할 수 있도록 단계별로 풀어냅니다.

> **핵심 키워드**: PDF to JSON 변환, 재무 보고서 데이터 추출, 파이썬 PDF 파싱

---

# # 1️⃣ PDF 구조 이해하기 – 페이지, 레이아웃, 텍스트 흐름

## # 1-1. PDF는 **벡터 이미지**와 **텍스트 스트림**이 혼합된 문서

- PDF 내부에는 글꼴, 좌표, 그래픽 명령어가 저장됩니다.

- 표는 실제로는 **텍스트와 좌표**가 격자 형태로 배치된 결과일 뿐, HTML 표와 같은 논리 구조가 없습니다.

## # 1-2. 왜 “복잡한 표”가 문제인가?

- 셀 병합, 다중 헤더, 페이지 나눔 등으로 인해 **좌표가 불규칙**합니다.

- 같은 열이라도 페이지마다 X 좌표가 미세하게 달라질 수 있습니다.

## # 1-3. 초보자를 위한 체크리스트

| 체크 항목 | 확인 방법 |

|---|---|

| PDF가 **텍스트 기반**인지 확인 | PDF 뷰어에서 텍스트 선택 가능 여부 |

| 페이지당 **표 위치**가 일정한가? | 페이지 미리보기(썸네일) 확인 |

| **이미지 기반** 스캔 PDF인가? | OCR 필요 여부 판단 |

---

# # 2️⃣ 파이썬 PDF 파싱 라이브러리 소개 – 선택과 활용

| 라이브러리 | 특징 | 설치 명령 |

|---|---|---|

| **pdfplumber** | 텍스트와 좌표, 표 추출에 강점 | `pip install pdfplumber` |

| **tabula-py** | Java 기반 Tabula와 연동, CSV/JSON 직접 변환 | `pip install tabula-py` |

| **camelot** | 정확한 테이블 감지, 스트리밍 모드 지원 | `pip install camelot-py[cv]` |

| **PyMuPDF (fitz)** | 빠른 페이지 렌더링, 이미지 추출에 유리 | `pip install pymupdf` |

| **OCR (Tesseract)** | 스캔 PDF 전용, 이미지 → 텍스트 변환 | `pip install pytesseract` + Tesseract 설치 |

> **초보자 팁**: 대부분의 재무 보고서는 텍스트 기반이므로 `pdfplumber`와 `camelot`을 조합하면 가장 효율적입니다.

---

# # 3️⃣ 실전 – 복잡한 재무 표를 JSON으로 추출하는 단계

## # 3-1. 프로젝트 구조 만들기

```
text

project/

│─ data/

│   └─ financial_report_Q1.pdf

│─ src/

│   ├─ extract_table.py

│   └─ utils.py

│─ output/

│   └─ report_Q1.json

└─ requirements.txt

```

## # 3-2. PDF 열기 & 페이지 순회 (pdfplumber)

```
python

import pdfplumber

pdf_path = 'data/financial_report_Q1.pdf'

pages = []

with pdfplumber.open(pdf_path) as pdf:

    for page in pdf.pages:

        pages.append(page)

```

## # 3-3. 표 감지와 좌표 정규화 (camelot)

```
python

import camelot

tables = camelot.read_pdf(

    pdf_path,

    pages='1-20',               # 전체 페이지

    flavor='stream',           # 복잡한 레이아웃에 적합

    edge_tol=500               # 셀 경계 허용치 확대

)

print(f'총 {len(tables)}개의 표가 추출되었습니다.')

```

## # 3-4. 표 전처리 – 헤더 통합 & 병합 셀 처리

```
python

import pandas as pd

def clean_table(df: pd.DataFrame) -> pd.DataFrame:

    # 1) 첫 번째 행을 헤더로 지정

    df.columns = df.iloc[0]

    df = df[1:].reset_index(drop=True)

    # 2) 공백 행/열 제거

    df = df.dropna(how='all').reset_index(drop=True)

    df = df.loc[:, ~df.isnull().all()]

    # 3) 숫자형 컬럼을 float 로 변환

    for col in df.columns:

        df[col] = pd.to_numeric(df[col].str.replace(',', ''), errors='ignore')

    return df

```

## # 3-5. JSON 변환 및 파일 저장

```
python

import json

from pathlib import Path

output = {}

for i, table in enumerate(tables):

    df = clean_table(table.df)

    output[f'table_{i+1}'] = df.to_dict(orient='records')

out_path = Path('output/report_Q1.json')

out_path.write_text(json.dumps(output, ensure_ascii=False, indent=4))

print(f'✅ JSON 파일이 저장되었습니다: {out_path}')

```

## # 3-6. 전체 흐름을 함수화 (extract_table.py)

```
python

def pdf_to_json(pdf_path: str, out_path: str) -> None:

    tables = camelot.read_pdf(pdf_path, pages='all', flavor='stream', edge_tol=500)

    result = {}

    for idx, tbl in enumerate(tables):

        df = clean_table(tbl.df)

        result[f'table_{idx+1}'] = df.to_dict(orient='records')

    Path(out_path).write_text(json.dumps(result, ensure_ascii=False, indent=4))

```

> **핵심 포인트**: `camelot`의 `flavor='stream'` 옵션은 **텍스트 기반 PDF**에서 셀 경계가 명확하지 않은 경우에 유용합니다. `edge_tol` 값을 조절해 표 감지 정확도를 높일 수 있습니다.

---

# # 4️⃣ 트러블슈팅 – 흔히 마주치는 오류와 해결법

| 문제 상황 | 원인 | 해결 방법 |

|---|---|---|

| **표가 전혀 추출되지 않음** | `flavor='lattice'` 사용 (이미지 기반) | `flavor='stream'` 로 전환 |

| **헤더가 데이터와 뒤섞임** | 첫 행에 공백 또는 병합 셀 존재 | `clean_table()` 함수에서 **첫 행을 강제 헤더**로 지정 |

| **숫자에 콤마(,)가 남아 변환 실패** | 문자열 그대로 저장 | `str.replace(',', '')` 후 `pd.to_numeric` 적용 |

| **페이지마다 열 위치가 미세하게 차이** | 좌표 오차 | `edge_tol` 값을 300~800 사이로 실험 |

| **스캔 PDF라 텍스트가 안 보임** | 이미지 기반 | `pytesseract`와 `pdf2image`를 사용해 OCR 수행 후 `pdfplumber`로 재처리 |

## # 4-1. OCR 연동 예시 (스캔 PDF)

```
python

from pdf2image import convert_from_path

import pytesseract

import pandas as pd

images = convert_from_path('data/scanned_report.pdf')

text_pages = [pytesseract.image_to_string(img, lang='kor+eng') for img in images]

# 이후 텍스트 기반 PDF와 동일하게 pdfplumber 로 파싱 가능

```

---

# # 5️⃣ 최적화 팁 – 대량 PDF 처리와 자동화

1. **멀티프로세싱**

   
```
python

   from concurrent.futures import ProcessPoolExecutor

   pdf_files = ['Q1.pdf', 'Q2.pdf', 'Q3.pdf']

   with ProcessPoolExecutor() as executor:

       executor.map(lambda p: pdf_to_json(p, f'output/{p[:-4]}.json'), pdf_files)

   
```

2. **클라우드 저장**

   - AWS S3에 JSON 파일을 바로 업로드하면 데이터 파이프라인 구축이 쉬워집니다.

   - `boto3` 라이브러리 활용: `s3_client.upload_file(out_path, bucket, key)`

3. **스케줄러**

   - `cron` 또는 `Airflow` 로 매월 신규 보고서 자동 수집·변환 파이프라인 구현

---

# # 🏁 결론 – 이제 당신도 재무 PDF를 JSON으로 자유롭게 변환할 수 있습니다!

복잡한 재무 보고서 PDF는 처음 보면 **“데이터 추출이 불가능할 정도로 난해하다”**는 인상을 줍니다. 하지만 **pdfplumber + camelot** 조합과 간단한 전처리 로직만으로도 대부분의 표를 정확히 추출하고, **JSON 형태**로 저장해 데이터 분석·시각화·AI 모델 학습에 바로 활용할 수 있습니다.

## # 👉 행동 유도

1. **오늘 바로 프로젝트 폴더를 만들고** 위 코드를 복사해 실행해 보세요.

2. **추출된 JSON 파일을 Pandas 혹은 PowerBI**에 연결해 시각화해 보면, 데이터가 살아 움직이는 것을 체감할 수 있습니다.

3. **추가적인 자동화**가 필요하다면, 멀티프로세싱·클라우드 스토리지·스케줄러를 차근차근 적용해 보세요.

**“PDF to JSON 변환”**이라는 키워드로 검색해도 좋은 자료가 많이 있지만, 직접 구현해 보는 경험이 가장 큰 힘이 됩니다. 이제 당신도 재무 보고서 데이터를 자유롭게 다룰 수 있는 **데이터 엔지니어**가 되었습니다! 🚀

---

*본 글은 **PDF to JSON 변환**, **재무 보고서 데이터 추출**, **파이썬 PDF 파싱**이라는 SEO 키워드를 중심으로 작성되었습니다. 검색 엔진 최적화를 위해 제목, 본문, 메타 설명 등에 동일 키워드를 자연스럽게 배치했습니다.*
