성능 벤치마크
이 페이지는 TCPDF-Next를 세 가지 주요 PHP PDF 라이브러리인 TCPDF, DomPDF, mPDF와 비교한 실제 벤치마크 결과를 제공합니다. 모든 수치는 동일한 Docker 환경에서 동일한 입력 문서를 사용하여 측정되었으며, 워밍업 라운드를 제외한 20회 측정의 중앙값(median)을 보고합니다. TCPDF-Next가 가장 빠르지 않은 경우에도 정직하게 공개합니다.
테스트 환경
| 파라미터 | 값 |
|---|---|
| CPU | Intel Core i9-13900K (x86-64) |
| RAM | 64 GB DDR5 (Docker 제한 16 GB) |
| Docker | 4 CPUs, 16 GB RAM, Ubuntu bookworm |
| PHP | 8.5.3 (CLI, OPcache 활성화, JIT 활성화) |
| TCPDF-Next | 1.6.0 |
| TCPDF-NextArtisan (Chrome) | 1.0.0 |
| TCPDF | 6.10.1 |
| DomPDF | v3.1.4 |
| mPDF | v8.2.7 |
| 워밍업 | 3회 (폐기) |
| 측정 | 20회 (중앙값 보고) |
| 시간 측정 | hrtime(true) 나노초 정밀도 벽시계 시간 |
TIP
모든 벤치마크는 Docker 기반으로 자동화되어 있으며, 누구나 동일한 환경에서 재현할 수 있습니다. 아래 벤치마크 재현 섹션을 참고하십시오.
인터랙티브 비교 차트
PHP 8.5.3 + OPcache + JIT · Docker 4 CPUs / 16 GB · i9-13900K · Median of 20 runs
생성 속도
각 시나리오는 워밍업 후 20회 실행되었습니다. 아래 표는 중앙값 생성 시간, 피크 메모리, 출력 파일 크기, TCPDF-Next 대비 상대 속도를 보여줍니다.
간단한 문서 (1페이지)
제목, 세 단락의 텍스트, 기본 서식(볼드, 이탤릭)으로 구성된 단일 A4 페이지입니다. 이미지나 테이블은 포함되지 않습니다.
| 라이브러리 | 시간 (ms) | 피크 메모리 (MB) | 파일 크기 (KB) |
|---|---|---|---|
| TCPDF-Next | 0.63 | 4 | 3 |
| TCPDF | 2.50 (3.97x 느림) | 12 (3.0x) | 7 (2.3x) |
| DomPDF | 4.07 (6.46x 느림) | 12 (3.0x) | 2 (0.7x) |
| mPDF | 7.13 (11.32x 느림) | 16 (4.0x) | 28 (9.3x) |
TCPDF-Next는 가장 간단한 시나리오에서 1ms 미만으로 완료됩니다. TCPDF보다 약 4배, DomPDF보다 약 6.5배, mPDF보다 약 11배 빠릅니다.
인보이스 (2페이지)
회사 로고, 고객 정보 테이블, 30행 품목 목록, 합계, 바닥글이 포함된 2페이지 인보이스입니다.
| 라이브러리 | 시간 (ms) | 피크 메모리 (MB) | 파일 크기 (KB) |
|---|---|---|---|
| TCPDF | 1.15 | 16 | 9 |
| TCPDF-Next | 1.64 | 16 | 52 |
| DomPDF | 19.09 (11.64x 느림*) | 16 | 4 |
| mPDF | 21.66 (13.21x 느림*) | 18 | 30 |
*TCPDF-Next 대비 상대 속도입니다.
정직한 참고
인보이스 시나리오에서는 레거시 TCPDF가 TCPDF-Next보다 1.4배 빠릅니다 (1.15 ms vs 1.64 ms). TCPDF는 또한 더 작은 출력 파일을 생성합니다 (9 KB vs 52 KB). 이는 TCPDF의 오랜 기간 최적화된 레거시 테이블 레이아웃 엔진이 단순한 표 형식 콘텐츠에서 약간의 우위를 가지기 때문입니다. 그럼에도 불구하고 두 라이브러리 모두 2ms 미만으로 실무 환경에서 체감 차이는 거의 없습니다. DomPDF와 mPDF는 10배 이상 느립니다.
100페이지 보고서
혼합 콘텐츠(제목, 단락, 임베디드 이미지, 머리글/바닥글)로 구성된 대용량 보고서입니다.
| 라이브러리 | 시간 (ms) | 피크 메모리 (MB) | 파일 크기 (KB) |
|---|---|---|---|
| TCPDF-Next | 32.39 | 18 | 96 |
| TCPDF | 102.47 (3.16x 느림) | 18 | 101 |
| mPDF | 1,044.05 (32.23x 느림) | 82 (4.6x) | 181 |
| DomPDF | 2,705.55 (83.52x 느림) | 70 (3.9x) | 129 |
100페이지 시나리오는 TCPDF-Next의 성능 우위가 가장 극적으로 드러나는 구간입니다. 32.39 ms로 TCPDF보다 3.2배 빠르고, DomPDF보다 83.5배 빠릅니다. 메모리 사용량은 TCPDF와 동일하며, DomPDF와 mPDF보다 현저히 낮습니다.
HTML→PDF 변환
HTML 마크업(제목, 단락, 링크, 기본 스타일)을 PDF로 변환하는 시나리오입니다. 두 가지 접근 방식을 비교합니다: 각 라이브러리의 내장 HTML 파서와 TCPDF-NextArtisan의 Chrome 렌더링 엔진입니다.
내장 HTML 파서
각 라이브러리에 내장된 HTML 파싱 엔진을 사용한 결과입니다.
| 라이브러리 | 시간 (ms) | 피크 메모리 (MB) | 파일 크기 (KB) |
|---|---|---|---|
| TCPDF-Next | 0.93 | 74 | 7 |
| TCPDF | 7.62 (8.19x 느림) | 74 | 13 |
| DomPDF | 16.09 (17.30x 느림) | 74 | 5 |
| mPDF | 33.62 (36.15x 느림) | 74 | 46 |
TCPDF-Next의 HTML 파싱 엔진은 1ms 미만의 성능을 제공합니다. TCPDF보다 8배, mPDF보다 36배 빠릅니다. 네 라이브러리 모두 피크 메모리가 74 MB로 유사합니다. 이는 HTML 파싱 인프라 자체의 오버헤드가 라이브러리 간 차이를 상쇄하기 때문입니다.
Chrome 렌더링 (TCPDF-NextArtisan)
TCPDF-NextArtisan은 Headless Chrome을 활용하여 HTML을 픽셀 퍼펙트 PDF로 변환합니다.
| 라이브러리 | 시간 (ms) | 피크 메모리 (MB) | 파일 크기 (KB) |
|---|---|---|---|
| TCPDF-NextArtisan (Chrome) | 309.85 | 74 | 37 |
Chrome 렌더링 지연 시간에 대한 설명
Artisan Chrome 렌더링의 309.85 ms는 내장 파서 대비 상당히 느리지만, 이는 의도적인 속도 vs 품질 트레이드오프입니다.
지연의 원인은 다음과 같습니다:
- Chrome Page 라이프사이클 오버헤드 — 복수의 CDP(Chrome DevTools Protocol) 왕복 통신이 필요합니다
printToPDF자체 소요 시간 — Chrome의 PDF 출력에 약 200~300 ms가 소요됩니다- PDF 파싱 + XObject 임포트 — Chrome이 생성한 PDF를 TCPDF-Next 문서로 가져오는 추가 오버헤드가 있습니다
- BrowserPool keep-alive 사용 중 — 브라우저 풀링을 통해 콜드 스타트를 방지하고 있지만, CDP 통신 오버헤드는 남습니다
핵심 차이점: DomPDF와 mPDF는 CSS 지원에 제한이 있어 복잡한 레이아웃을 정확하게 렌더링하지 못하는 경우가 많습니다. 반면 Artisan은 Chrome의 완전한 렌더링 엔진을 사용하므로 Flexbox, Grid, 미디어 쿼리, 웹 폰트 등 모든 최신 CSS를 지원하며 픽셀 퍼펙트 출력을 보장합니다. 시각적 정확성이 중요한 문서에서는 Artisan이 최적의 선택입니다.
피크 메모리 사용량
각 시나리오에서 memory_get_peak_usage(true)로 측정한 피크 메모리(MB)입니다. 값이 낮을수록 효율적입니다.
| 시나리오 | TCPDF-Next | TCPDF | DomPDF | mPDF |
|---|---|---|---|---|
| 간단한 문서 | 4 MB | 12 MB | 12 MB | 16 MB |
| 인보이스 | 16 MB | 16 MB | 16 MB | 18 MB |
| 100페이지 | 18 MB | 18 MB | 70 MB | 82 MB |
| HTML→PDF (내장 파서) | 74 MB | 74 MB | 74 MB | 74 MB |
간단한 문서에서 TCPDF-Next는 TCPDF/DomPDF 대비 3분의 1, mPDF 대비 4분의 1의 메모리만 사용합니다. 100페이지 보고서에서는 DomPDF(70 MB)와 mPDF(82 MB)가 TCPDF-Next/TCPDF(18 MB)보다 약 4배의 메모리를 소비합니다.
HTML→PDF 시나리오에서는 네 라이브러리 모두 74 MB로 동일한 메모리를 사용합니다. 이는 HTML 파싱에 필요한 DOM 트리 구조의 오버헤드가 라이브러리 간 차이를 상쇄하기 때문입니다.
파일 크기
생성된 PDF 파일의 크기(KB)입니다. 값이 낮을수록 작습니다.
| 시나리오 | TCPDF-Next | TCPDF | DomPDF | mPDF |
|---|---|---|---|---|
| 간단한 문서 | 3 KB | 7 KB | 2 KB | 28 KB |
| 인보이스 | 52 KB | 9 KB | 4 KB | 30 KB |
| 100페이지 | 96 KB | 101 KB | 129 KB | 181 KB |
| HTML→PDF (내장 파서) | 7 KB | 13 KB | 5 KB | 46 KB |
파일 크기는 시나리오에 따라 결과가 다릅니다. DomPDF는 간단한 문서와 인보이스에서 가장 작은 파일을 생성합니다. 이는 DomPDF가 최소한의 메타데이터와 간소화된 PDF 구조를 사용하기 때문입니다. 반면 대용량 문서(100페이지)에서는 TCPDF-Next가 가장 작은 파일을 생성하며, 이는 PDF 2.0의 바이너리 크로스 레퍼런스 스트림과 객체 스트림 압축 덕분입니다.
처리량 (Throughput)
간단한 1페이지 문서를 기준으로 초당/분당 생성 가능한 PDF 수를 측정합니다. 지속적인 부하 조건에서 각 라이브러리가 처리할 수 있는 문서 수를 나타냅니다.
초당 처리량
| 모드 | TCPDF-Next | TCPDF | DomPDF | mPDF |
|---|---|---|---|---|
| 싱글 스레드 | 2,684 | 1,244 | 260 | 133 |
| 4 워커 | 9,434 | 4,431 | 939 | 484 |
분당 처리량
| 모드 | TCPDF-Next | TCPDF | DomPDF | mPDF |
|---|---|---|---|---|
| 싱글 스레드 | 161,014 | 74,626 | 15,588 | 7,994 |
| 4 워커 | 566,024 | 265,832 | 56,334 | 29,044 |
4 워커 병렬 처리 시 TCPDF-Next는 초당 약 9,434건, 분당 약 566,024건의 PDF를 생성할 수 있습니다. 이는 TCPDF 대비 2.1배, DomPDF 대비 10배, mPDF 대비 약 19.5배의 처리량입니다. 대량 PDF 생성이 필요한 엔터프라이즈 환경(인보이스 발행, 보고서 생성, 명세서 출력)에서 이러한 처리량 차이는 인프라 비용 절감으로 직결됩니다.
디지털 서명 오버헤드 (PAdES)
TCPDF-Next는 PAdES(PDF Advanced Electronic Signatures) 표준을 지원하는 유일한 PHP PDF 라이브러리입니다. 아래는 10페이지 문서에 각 PAdES 수준의 서명을 적용할 때 추가되는 오버헤드입니다.
| 서명 수준 | 추가 시간 (ms) | 추가 파일 크기 (KB) | 설명 |
|---|---|---|---|
| PAdES B-B | +15 | +5~8 | 기본 서명 (CMS 서명 내장) |
| PAdES B-T | +120* | +8~12 | 신뢰할 수 있는 타임스탬프 추가 |
| PAdES B-LT | +250* | +15~50 | 장기 검증 데이터 내장 (인증서 체인 + OCSP/CRL) |
| PAdES B-LTA | +350* | +20~60 | 아카이브 타임스탬프 추가 (장기 보존용) |
*TSA/OCSP 서버로의 네트워크 왕복 시간이 포함되어 있습니다. 실제 시간은 서버 지연 시간과 네트워크 환경에 따라 달라집니다.
TIP
PAdES B-B(기본 서명)는 약 15 ms와 5~8 KB만 추가하므로 대부분의 워크플로우에서 무시할 수 있는 수준입니다. B-T 이상의 수준은 타임스탬프 기관(TSA)과 OCSP 응답 서버 호출로 인한 네트워크 종속 지연이 발생합니다. PAdES B-B 수준은 네트워크 호출 없이 로컬에서 완료되므로 오프라인 환경에서도 사용할 수 있습니다.
PDF/A-4 아카이브 오버헤드
PDF/A-4는 장기 보존을 위한 국제 표준(ISO 19005-4)입니다. 표준 PDF 2.0 출력 대비 PDF/A-4 규정 준수 출력을 생성할 때의 추가 오버헤드입니다.
| 구성 요소 | 추가 크기 |
|---|---|
| sRGB ICC 프로파일 | +3 KB |
| XMP 메타데이터 | +2~5 KB |
| 출력 인텐트 | +1~3 KB |
| 전체 폰트 임베딩 (필요한 경우) | 폰트당 +50~500 KB |
| 일반적 총 오버헤드 | +10~50 KB |
| 생성 시간 오버헤드 | < 5% |
TIP
PDF/A-4 모드에서도 폰트 서브셋팅이 기본적으로 적용됩니다. 오버헤드의 대부분은 ICC 프로파일과 확장된 XMP 메타데이터에서 발생하며, 실제 문서 크기에 비해 미미한 수준입니다.
TCPDF-Next가 빠른 이유
TCPDF-Next의 성능 우위는 의도적인 아키텍처 설계에 기반합니다.
최신 PDF 2.0 코어 — 렌더링 파이프라인을 PDF 2.0 전용으로 처음부터 구축하여, TCPDF를 느리게 만드는 레거시 호환성 레이어를 제거했습니다. 크로스 레퍼런스 스트림과 객체 스트림으로 I/O와 파일 크기를 동시에 줄입니다.
JIT 친화적 코드 패스 — 핫 루프와 핵심 렌더링 메서드는 PHP 8의 JIT 컴파일러가 효율적인 머신 코드를 생성할 수 있도록 구조화되었습니다. 타이트하고 타입이 지정된 코드와 최소한의 분기로 JIT 최적화를 극대화합니다.
지연 리소스 로딩 — 폰트, 이미지, ICC 프로파일은 생성 시점이 아닌 최초 사용 시점에 로딩됩니다. 이미지를 포함하지 않는 문서에서는 이미지 처리 오버헤드가 전혀 발생하지 않습니다.
효율적인 메모리 레이아웃 — 페이지 객체는 압축되며, 공유 리소스(폰트, 색상 공간)를 참조 카운팅을 통해 재사용합니다. 이를 통해 긴 문서에서도 피크 메모리를 낮게 유지합니다.
최적화된 HTML 파서 — 레거시 TCPDF의 정규식 기반 HTML 파싱 대신, TCPDF-Next는 스트리밍 토큰 기반 파서를 사용하여 HTML을 단일 패스로 처리하며 최소한의 백트래킹으로 동작합니다.
병렬화 가능한 설계 — 상태 없는(stateless) 페이지 렌더링 아키텍처 덕분에 워크로드가 여러 워커에 걸쳐 선형적으로 확장됩니다. 4 워커 사용 시 거의 4배에 가까운 처리량 향상이 이를 입증합니다.
테스트 방법론
벤치마크의 공정성과 재현성을 보장하기 위해 다음 방법론을 적용했습니다.
| 항목 | 설명 |
|---|---|
| 워밍업 | 측정 전 3회의 워밍업 이터레이션을 실행하고 결과를 폐기합니다. 이를 통해 OPcache와 JIT가 완전히 워밍업됩니다. |
| 이터레이션 | 시나리오별 20회 측정 후 중앙값(median)을 보고합니다. 중앙값은 이상치(outlier) 노이즈를 제거하기 위해 사용됩니다. |
| 시간 측정 | hrtime(true)를 사용하여 나노초 정밀도의 벽시계 시간(wall-clock time)을 측정합니다. microtime()의 클록 드리프트 문제를 방지합니다. |
| 메모리 측정 | memory_get_peak_usage(true)로 PHP 런타임이 할당한 실제(RSS) 피크 메모리를 측정합니다. |
| 파일 크기 | 출력을 임시 파일에 기록하고 filesize()로 측정합니다. |
| 격리 환경 | 각 벤치마크는 자체 프로세스에서 실행하여 테스트 간 메모리 오염을 방지합니다. |
| 동일 환경 | 모든 라이브러리가 동일한 Docker 컨테이너에서 동일한 PHP 설정, CPU 제한, 메모리 제한으로 실행됩니다. |
| 동일 입력 | 모든 라이브러리가 동일한 입력 데이터(텍스트, 이미지, HTML)를 사용합니다. |
| 공정한 설정 | 각 라이브러리의 기본 설정(default configuration)을 사용합니다. 특정 라이브러리에 유리한 튜닝은 적용하지 않았습니다. |
벤치마크 재현
벤치마크 스위트는 저장소에 포함되어 있습니다. 아래 Docker 명령어로 동일한 벤치마크를 직접 실행할 수 있습니다.
# 1. 저장소 클론
git clone https://github.com/nicoapps/tcpdf-next.git
cd tcpdf-next
# 2. Docker 이미지 빌드 및 벤치마크 실행
cd benchmark
docker compose up --build
# 3. 또는 개별 시나리오 실행
docker build -t tcpdf-bench -f benchmark/Dockerfile .
docker run --rm --cpus=4 --memory=16g tcpdf-bench \
php benchmark/run.php --scenario=simple
docker run --rm --cpus=4 --memory=16g tcpdf-bench \
php benchmark/run.php --scenario=invoice
docker run --rm --cpus=4 --memory=16g tcpdf-bench \
php benchmark/run.php --scenario=100page
docker run --rm --cpus=4 --memory=16g tcpdf-bench \
php benchmark/run.php --scenario=html2pdf
# 4. 처리량 테스트 (4 워커)
docker run --rm --cpus=4 --memory=16g tcpdf-bench \
php benchmark/run.php --throughput --workers=4
# 5. 결과를 JSON으로 내보내기
docker run --rm --cpus=4 --memory=16g tcpdf-bench \
php benchmark/run.php --all --format=json > results.json결과는 실행 종료 시 stdout으로 출력됩니다. Docker 설정으로 호스트 OS에 관계없이 동일한 환경이 보장됩니다.
INFO
벤치마크 실행에는 약 10~15분이 소요됩니다. --scenario 옵션으로 특정 시나리오만 실행하면 시간을 단축할 수 있습니다.
관련 문서
- 마이그레이션 가이드 -- TCPDF, DomPDF, mPDF에서 마이그레이션하는 방법
- 성능 최적화 -- 스트리밍 모드와 메모리 튜닝 전략
- 디지털 서명 -- PAdES 서명 가이드
- PDF/A 규정 준수 -- PDF/A-4 아카이브 출력 가이드
- 설치 가이드 -- TCPDF-Next 설치 및 시작하기
- Artisan Chrome 렌더링 -- Headless Chrome HTML→PDF 변환 가이드