소개
청구서 통합은 GroupDocs.Merger for Python을 사용하여 여러 재무 문서를 하나의 PDF로 결합하는 워크플로우입니다. 재무 팀은 종종 청구서와 함께 납품서, 서비스 보고서, 보증 조건 등을 보내야 하지만 파일을 수동으로 이어 붙이면 오류가 발생하고 시간이 낭비됩니다. GroupDocs.Merger는 이 과정을 자동화하여 모든 첨부 파일이 올바른 순서대로 정렬되고, 필요에 따라 보안이 적용되며, 깔끔한 하나의 PDF로 전달되도록 보장합니다.
이 튜토리얼에서는 다음을 확인합니다.
- 일반 PDF 청구서를 지원 파일과 병합하기
- JPG 이미지와 DOCX 계약서와 같은 혼합 형식 처리하기
- 비밀번호로 보호된 청구서를 열고, 첨부 파일을 추가한 뒤 다시 암호를 적용하기
- 큰 첨부 파일에서 선택된 페이지만 포함하여 최종 번들을 가볍게 유지하기
지난 분기에 회계 시스템이 비밀번호로 보호된 청구서를 생성하고 법무팀이 다중 페이지 보증 DOCX를 추가했을 때 바로 이 시나리오에 직면했습니다. 아래 코드는 5분 이내에 문제를 해결했습니다.
비밀번호로 보호된 청구서를 다른 문서와 병합하는 것이 언제 의미가 있나요?
많은 기업이 규정 준수를 위해 청구서를 저장 시 암호화합니다. 청구서를 고객에게 비보호 첨부 파일(영수증, 약관, 이미지 등)과 함께 보내야 할 경우, 병합을 위해 원본 비밀번호를 해제한 뒤 최종 번들에 다시 적용해야 합니다. GroupDocs.Merger를 사용하면 LoadOptions를 통해 해제 비밀번호를 제공하고, 추가 파일을 결합한 뒤 AddPasswordOptions로 병합된 PDF에 다시 비밀번호를 설정할 수 있습니다. 이렇게 하면 기밀성을 유지하면서 하나의 쉽게 열 수 있는 문서를 전달할 수 있습니다.
사전 요구 사항
- Python 3.8+ (.NET 브리지 사용)
- GroupDocs.Merger for Python – 설치:
pip install groupdocs-merger
- 청구서 PDF(
invoice.pdf)와 첨부 파일 경로 목록 - (선택) 원본 청구서와 출력 PDF에 대한 비밀번호
Step 1: PDF 첨부 파일 기본 통합
가장 간단한 경우는 PDF 청구서를 다른 PDF, 이미지 또는 Word 파일과 병합하는 것입니다. API는 비PDF 입력을 자동으로 PDF로 변환한 뒤 결합합니다.
import groupdocs_merger as gm
# Paths to source files
invoice = "invoice.pdf"
attachments = ["delivery_note.pdf", "service_report.pdf"]
output = "billing_package.pdf"
with gm.Merger(invoice) as merger:
for path in attachments:
merger.join(path) # Normalises each file to PDF and appends it
merger.save(output)
핵심 포인트:
gm.Merger는 호스트 문서(청구서)와 함께 인스턴스화됩니다.join()은 지원되는 모든 형식을 받아들이며, 라이브러리가 변환을 처리합니다.save()는 병합된 PDF를 지정된 경로에 기록합니다.
Step 2: 혼합 형식 첨부 파일 통합
실제 청구 패키지는 스캔 이미지(JPG)와 법률 계약서(DOCX)를 포함하는 경우가 많습니다. 같은 코드가 작동하는 이유는 GroupDocs.Merger가 모든 첨부 파일을 실시간으로 PDF로 정규화하기 때문입니다.
attachments = ["receipt.jpg", "warranty_terms.docx", "extra_clause.pdf"]
output = "billing_mixed.pdf"
with gm.Merger(invoice) as merger:
for path in attachments:
merger.join(path) # JPG and DOCX are converted to PDF automatically
merger.save(output)
왜 중요한가: 모든 파일을 PDF로 변환하면 수신자가 여러 뷰어를 번갈아 사용할 필요가 없어 원활한 경험을 제공합니다.
Step 3: 비밀번호로 보호된 청구서 처리
청구서가 암호화된 경우 LoadOptions를 통해 비밀번호를 제공합니다. 병합 후에는 AddPasswordOptions를 사용해 최종 PDF에 다시 비밀번호를 적용할 수 있습니다.
import io
invoice_password = "Inv$2026"
output_password = "Bill$2026"
load_options = gm.domain.options.LoadOptions(invoice_password)
buffer = io.BytesIO()
# Open the protected invoice, join attachments, write to memory buffer
with gm.Merger(invoice, load_options) as merger:
for path in attachments:
merger.join(path)
merger.save(buffer)
# Re‑secure the merged document
add_pwd = gm.domain.options.AddPasswordOptions(output_password)
buffer.seek(0)
with gm.Merger(buffer) as merger:
merger.add_password(add_pwd)
merger.save(output)
핵심 포인트:
LoadOptions는 원본 PDF의 잠금을 해제합니다.- 병합 결과는 먼저 메모리 스트림(
BytesIO)에 기록됩니다. AddPasswordOptions는 최종 파일에 새 비밀번호를 적용합니다.
Step 4: 첨부 파일에서 특정 페이지 선택
때때로 첨부 파일 중 일부 페이지만 필요할 수 있습니다(예: 긴 서비스 보고서의 첫 두 페이지). PageJoinOptions를 사용해 포함할 1‑기반 페이지 범위를 지정합니다.
page_picks = [
("service_report.pdf", 1, 2), # Include pages 1‑2 only
("terms_and_conditions.pdf", 3, 3) # Include only page 3
]
output = "billing_selected_pages.pdf"
with gm.Merger(invoice) as merger:
for path, first, last in page_picks:
options = gm.domain.options.PageJoinOptions(first, last)
merger.join(path, options)
merger.save(output)
결과: 최종 PDF에는 청구서와 선택된 페이지만 포함되어 번들이 가볍게 유지됩니다.
모범 사례 및 팁
- 성능: 대용량 배치에서는 필요한 옵션만 활성화하세요(예: 불필요한 형식 변환 방지).
- 메모리 관리:
with