비동기 PDF 처리
PDF Oxide는 Python, C#, Node.js에서 일급 비동기 API를 제공하므로 추출 작업이 이벤트 루프나 HTTP 요청 핸들러를 절대 막지 않습니다. 동일한 PdfDocument 메서드가 백그라운드 스레드/스레드 풀로 디스패치되는 비동기 래퍼로 노출됩니다.
Python — AsyncPdfDocument
PdfDocument의 모든 메서드는 AsyncPdfDocument에 awaitable 형태의 대응 메서드를 가집니다. 각 호출은 동기 메서드를 asyncio.to_thread()로 감쌉니다.
Python
import asyncio
from pdf_oxide import AsyncPdfDocument
async def extract(path):
doc = await AsyncPdfDocument.open(path)
text = await doc.extract_text(0)
return text
asyncio.run(extract("report.pdf"))
여러 페이지에 걸친 팬아웃
Python
import asyncio
from pdf_oxide import AsyncPdfDocument
async def extract_all(path):
doc = await AsyncPdfDocument.open(path)
page_count = await doc.page_count()
pages = await asyncio.gather(*[doc.extract_text(i) for i in range(page_count)])
return pages
생성
AsyncPdf는 생성 흐름을 위해 Pdf 클래스를 그대로 미러링합니다:
Python
from pdf_oxide import AsyncPdf
pdf = await AsyncPdf.from_markdown("# Hello")
await pdf.save_async("out.pdf")
Office 변환
AsyncOfficeConverter는 DOCX / XLSX / PPTX → PDF 비동기 변환을 처리합니다.
Python
from pdf_oxide import AsyncOfficeConverter
converter = AsyncOfficeConverter()
pdf_bytes = await converter.docx_to_pdf_bytes("input.docx")
자유 스레드 Python (cp314t)
pdf_oxide 확장 모듈은 gil_used = false를 선언하므로 cp314t(Python 3.14 자유 스레드 빌드)에서 안전하게 사용할 수 있습니다. 여러 스레드가 GIL 직렬화 없이 PdfDocument 메서드를 병렬로 호출할 수 있습니다.
Python
from concurrent.futures import ThreadPoolExecutor
from pdf_oxide import PdfDocument
doc = PdfDocument("large.pdf")
with ThreadPoolExecutor(max_workers=8) as pool:
pages = list(pool.map(doc.extract_text, range(doc.page_count())))
C# — CancellationToken을 사용하는 async Task<T>
모든 추출 및 저장 메서드는 Task<T>를 반환하고 선택적 CancellationToken을 받는 *Async 변형을 가집니다.
C#
using PdfOxide.Core;
using var doc = PdfDocument.Open("report.pdf");
string text = await doc.ExtractTextAsync(0);
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30));
var tasks = Enumerable.Range(0, doc.PageCount)
.Select(i => doc.ExtractTextAsync(i, cts.Token));
string[] pages = await Task.WhenAll(tasks);
에디터
C#
using var editor = DocumentEditor.Open("form.pdf");
editor.SetFormFieldValue("name", "Jane Doe");
await editor.SaveAsync("filled.pdf");
Node.js — *Async 메서드
모든 동기 메서드는 비동기 형제 메서드를 가집니다 — extractText → extractTextAsync, save → saveAsync 등. 비동기 호출은 libuv 스레드 풀에서 실행됩니다.
Node.js
const { PdfDocument } = require("pdf-oxide");
async function extractAll(path) {
const doc = new PdfDocument(path);
try {
const pageCount = doc.getPageCount();
const pages = await Promise.all(
Array.from({ length: pageCount }, (_, i) => doc.extractTextAsync(i))
);
return pages;
} finally {
doc.close();
}
}
HTTP 핸들러 예제
Node.js
import express from "express";
import { PdfDocument } from "pdf-oxide";
const app = express();
app.post("/extract", express.raw({ type: "application/pdf", limit: "50mb" }), async (req, res) => {
const doc = PdfDocument.openFromBytes(req.body);
try {
const text = await doc.extractTextAsync(0);
res.json({ text });
} finally {
doc.close();
}
});
동시성 모델
| 언어 | 메커니즘 |
|---|---|
| Python | asyncio.to_thread가 동기 호출을 기본 executor로 디스패치 |
| Python (cp314t) | 진정한 스레드 병렬성 — GIL은 선택 사항 |
| C# | Task 기반 비동기 패턴, ThreadPool로 디스패치 |
| Node.js | libuv 워커 스레드 (Napi::AsyncWorker) |
| Go | 불필요 — 고루틴이 동기 메서드를 직접 호출 |
| Rust | 제공하지 않음 — tokio::task::spawn_blocking이나 원하는 executor 사용 |
여러 스레드 간에 단일 PdfDocument를 공유하는 방법은 동시성 가이드를 참고하세요.
관련 문서
- 동시성 — 스레드 안전성 + 병렬 읽기
- Python 시작하기
- Node.js 시작하기
- C# 시작하기