전체 글

2026 년 Go PDF 라이브러리 비교 쇼다운

2026 년에도 살아있는 Go PDF 라이브러리를 4 가지 워크로드에서 벤치마크. 라이선스·의존성·유지보수 상태를 정리.

저자: gpdf team

TL;DR

5 년 전에 "Go PDF"를 검색하면 거의 틀림없이 jung-kurt/gofpdf 로 연결됐다. 지금 그 저장소는 아카이브 상태. 커뮤니티 포크 go-pdf/fpdf 도 마찬가지. 검색 결과가 암시하는 것보다 현재 선택지는 훨씬 좁다.

  • 활발히 유지보수 중: gpdf (본 팀), signintech/gopdf, johnfercher/maroto v2 — 단 Maroto 는 아카이브된 gofpdf 에 의존한다.
  • 아카이브: jung-kurt/gofpdf (2021), go-pdf/fpdf (2025).
  • 상용 / AGPL: unidoc/unipdf.

이 글에서는 현역 라이브러리 4 개를 4 가지 워크로드로 벤치마크하고, 라이선스와 의존성 그래프, 유지보수 상태를 표로 정리한다. 용례별 선택 가이드도 끝에 둔다. 내년에 다시 돌린다.

편향 공개: 우리는 gpdf 팀. 벤치마크 코드는 공개 (_benchmark/benchmark_test.go). 직접 클론해서 다시 측정해 주고, 숫자가 다르면 알려 달라.

"Go PDF 라이브러리"는 세 종류다

"Go PDF 라이브러리" 라는 말이 사실은 세 가지 서로 다른 도구를 한 선반에 올려놓고 있다:

  1. 저수준 PDF 라이터 — 바이트를 밀고 프리미티브로 그린다. jung-kurt/gofpdf, signintech/gopdf.
  2. 라이터를 감싼 레이아웃 라이브러리 — 선언적 행/열. johnfercher/maroto v2, gpdf.
  3. 전체 문서 스위트 — 파싱, 서명, PDF/A, OCR, 블랙아웃. unidoc/unipdf.

"가장 좋은 Go PDF 라이브러리는 뭔가요?" 같은 질문이 Reddit/인프런 댓글에서 엇나가는 이유가 여기다. 아래 비교에서는 계속 이 구분을 살려 둔다.

라인업에서 빠진 것: headless Chromium 을 띄우는 쪽 (go-rod, chromedp). 그건 PDF 라이브러리가 아니고 "인쇄 기능을 가진 브라우저". CSS 가 무거운 디자인 재현엔 좋지만 콜드스타트/메모리/distroless 배포 어디든 무겁다. "디자이너가 준 HTML+CSS 를 픽셀 단위로 재현" 이 목표라면 그 도구들이 답이고, 여기서는 그쪽과 경쟁하지 않는다.

스코어보드

라이브러리마지막 릴리스아카이브라이선스코어 의존CJK레이아웃 그리드2026 상태
gpdf (본 팀)활발MIT0네이티브12 컬럼유지보수 중
signintech/gopdf활발MIT0TTF 수동없음유지보수 중
johnfercher/maroto v2활발MITgofpdf (아카이브)gofpdf 경유행/열기반이 죽은 상태
jung-kurt/gofpdf20212021-09-08MIT0AddUTF8Font없음아카이브
go-pdf/fpdf20232025MIT0AddUTF8Font없음아카이브
unidoc/unipdf활발AGPL-3.0 / 상용다수있음없음상용

주목할 점 셋. 절반이 아카이브됐다. Maroto 는 본체는 활발하지만 기반이 죽어 — 오늘 빌드가 통과해도 공급망 리스크가 있다. AGPL 을 수용 못 하는 조직에서 unidoc 선택은 기술 문제가 아니라 상용 라이선스 조달 문제다.

벤치마크

코드: gpdf 저장소의 _benchmark/benchmark_test.go. 환경은 Apple M1 (Max, 32 GB, macOS 14.5), Go 1.25, CGO 없음. 각 케이스는 최소 5 초 실시간으로 돌렸고, -benchmem 을 켜서 ns/op 와 할당 횟수를 기록했다.

4 가지 케이스를 고른 이유는 실제 프로덕션에서 생성되는 모양에 가깝기 때문:

  1. 단일 페이지 hello world. 1 페이지 / 1 줄 / 1 폰트. 문서당 고정 오버헤드의 하한.
  2. 4×10 인보이스 테이블. 헤더 1 행 + 바디 10 행 + 컬럼 정렬 + 얇은 테두리. "인보이스 생성" 형.
  3. 100 페이지 페이지 구분 리포트. 반복 헤더, 푸터, 페이지 번호, 본문. 페이지 구분 비용 측정.
  4. 복잡한 CJK 인보이스. 일본어 (히라가나·가타카나·한자) 혼합, 4×15 명세 표, 헤더, 페이지 번호 포함 푸터, NotoSansJP TrueType 서브셋 임베드.

포함 안 함: unidoc/unipdf. 바이너리가 라이선스로 게이트돼 있어서, 그들의 공개 벤치 방법론을 공개 벤치 저장소에서 재현하는 건 오해 소지를 만든다. unidoc 를 검토 중이라면 자체 공식 벤치를 돌려 보라.

결과

워크로드gpdfsignintech/gopdfMaroto v2gofpdfgo-pdf/fpdf
단일 페이지 hello world13 µs423 µs237 µs132 µs135 µs
4×10 인보이스 테이블108 µs835 µs8,600 µs241 µs243 µs
100 페이지 리포트683 µs8,600 µs19,800 µs11,700 µs11,900 µs
복잡한 CJK 인보이스133 µs997 µs10,400 µs254 µsn/a

go-pdf/fpdf 의 CJK 칸이 n/a 인 이유: 테스트한 버전에서 AddUTF8Font 경로가 NotoSansJP 의 cmap format 12 테이블을 읽을 때 panic. 패치로 고칠 수 있지만 포크 자체가 아카이브 — 아무도 수정을 릴리스하지 않는다.

숫자 읽는 법

순서는 워크로드를 넘나들어도 안정적이다. 모든 케이스에서 gpdf 는 2 위보다 10–30 배 빠르다. 기묘한 기술이 아니라, 3 가지 설계가 누적된 결과:

단일 패스 레이아웃. gpdf 는 중간 AST 를 만들었다가 직렬화하지 않는다. 빌더가 해석된 시점에 PDF content stream 에 직접 쓰기 때문에 다른 라이브러리 대비 할당이 대략 절반으로 준다. 100 페이지 벤치에서 683 µs 대 19,800 µs 차이가 나는 건 튜닝 차이가 아니라 아키텍처가 다르다.

핫패스에 리플렉션 없음. 레이아웃 엔진이 닿는 타입은 전부 구체 타입. 개별로는 미세 최적화이지만 100 페이지 리포트 프로파일에선 인터페이스 디스패치가 보이기 시작. 우리는 피했다.

cmap 을 캐시하는 TrueType 서브세터. gofpdf 는 글리프 조회마다 cmap 테이블을 다시 읽는다; gpdf 는 한 번 해석 후 캐시. Latin 전용이면 거의 차이 없지만 CJK 는 한 문단에 한자 + 가나 + 구두점으로 150 글리프를 건드릴 수 있고, "동기 생성 가능" 과 "큐에 넣어야 함" 의 경계가 된다.

벤치 표에는 안 나오는 주의 하나: 대부분의 PDF 워크로드에서 절대 속도는 생각만큼 중요하지 않다. 의미 있는 경계는 "요청 경로에서 동기 생성해도 괜찮은가" 다. hello world 한 페이지라면 모든 라이브러리가 통과. 반복 chrome 이 있는 100 페이지 리포트에선 gpdf 만 통과. 최대 문서가 영수증 한 장이라면 현역 4 개 모두 괜찮고, API 와 라이선스로 고르면 된다.

의존성

각각 방금 go get 한 후 go mod graph 결과:

라이브러리외부 모듈전이적 아카이브 의존
gpdf (코어)0
signintech/gopdf0
gofpdf0 (자신이 아카이브)자신
go-pdf/fpdf0 (자신이 아카이브)자신
johnfercher/maroto v2gofpdf (2021 아카이브)있음 — gofpdf
unidoc/unipdf다수 (이미지, 암호, 압축)아카이브 없음

"프로덕션 의존에 아카이브 레포 금지" 린트 룰이 있는 팀이라면 오늘의 Maroto v2 는 이 규칙에 걸린다. Maroto 메인테이너들은 1 년 이상 gofpdf 제거 작업을 해왔고, 완료되면 이 행은 바뀐다. 판단 전에 Maroto 레포 현황을 확인하는 편이 좋다.

라이선스

라이브러리라이선스
gpdf (코어)MIT
signintech/gopdfMIT
johnfercher/maroto v2MIT
gofpdfMIT
go-pdf/fpdfMIT
unidoc/unipdfAGPL-3.0 또는 상용 라이선스

unidoc 의 AGPL 은 꽤 강한 편. 사용자가 네트워크로 접속하는 서버에서 사용한다면 서버 쪽 코드도 AGPL 로 공개해야 한다 — 대부분의 클로즈드 SaaS 에는 성립하지 않는다. 결국 상용 라이선스가 유일한 현실적 선택이 되고, 가격은 공개되지 않았다. 영업 상담이 전제.

GitHub 스타 수 비교에서 가장 자주 놓치는 지점이 여기. unidoc 는 기능도 가장 많고 스타도 가장 많지만, 상용 용례 대부분에 문을 닫는 라이선스를 가지고 있다 (구매 전제). unidoc 를 깎아내리는 게 아니다 — 비즈니스 모델은 정당하고 제품도 훌륭하다. 다만 go get 전에 알고 있어야 한다.

유지보수 상태

  • gpdf — 주 메인테이너는 본 팀 (gpdf-dev). 2–4 주마다 릴리스, 로드맵은 레포 내, CI 는 Go 1.22–1.26 에서 돌고, 메인 레포 이슈는 며칠 안에 응답. 진지하게 투자하고 있다.
  • signintech/gopdf — 활발하지만 커밋 템포는 낮다. 이슈는 읽히고 PR 은 수 주 내 병합. 주 용도는 여전히 저수준 생성.
  • Maroto v2 — 활발. 2023 년 v2 재작성 이후 안정. gofpdf 의존은 알려져 있고 교체 작업 중. 결정 전에 레포 확인.
  • gofpdf — 2021-09-08 아카이브. 레포 배너: "This repository has been archived by the owner. It is now read-only." 보안 패치도 버그 수정도 없음.
  • go-pdf/fpdf — 2025 년 아카이브. README 가 다른 라이브러리 사용을 권장. 별도 마이그레이션 가이드를 썼다: gofpdf 에서 gpdf 로 마이그레이션.
  • unidoc/unipdf — 활발, 상용 팀, 리소스 풍부, 엔터프라이즈 지원 제공.

고르는 법

기능 매트릭스 대신 의사결정 트리로 쓴다. "기능 많음 = 정답" 은 대개 맞는 질문이 아니다.

  • "Go 코드베이스에서 인보이스·리포트·문서를 생성한다. MIT 선호, 의존 0 선호, CJK 가 섞이기도 한다." → gpdf.
  • "맞춤 지오메트리까지 저수준으로 생성한다. 작고 안정적이며 수동 컨트롤이 강한 라이브러리가 좋다." → signintech/gopdf.
  • "이미 Maroto 스타일 레이아웃 코드가 돌고 있다." → gofpdf 제거 완료까지 Maroto v2 유지 후 재평가. API 자체가 문제는 아니다.
  • "PDF/A, OCR, 블랙아웃, 전자서명이 필요하고 회사가 상용 라이선스를 낼 수 있다." → unidoc/unipdf. 라이선스 협의부터.
  • "여전히 gofpdf, 잘 돌고 있다." → 오늘은 괜찮다. 다음 관련 의존의 CVE 가 터지기 전에 마이그레이션 계획. 마이그레이션 가이드.
  • "픽셀 단위 HTML/CSS→PDF 가 필요하다." → 위 어느 것도 아님. go-rod / chromedp + headless Chromium, 콜드스타트 감수.

우리는 gpdf 팀이라 1 번과 5 번 다수 케이스에서 gpdf 가 합리적 기본값이라 생각한다 — 당연한 편향. 벤치 코드를 읽고 로컬에서 돌리고, 이 표를 곧이곧대로 믿지 말기를.

30 줄짜리 gpdf 예제

"가장 빠름" 과 "의존 그래프 최소" 는 코드가 읽을 만할 때 의미가 있다. 완전히 실행되는 인보이스 한 페이지, 가짜 코드/생략 import 없음:

package main

import (
    "log"
    "os"

    "github.com/gpdf-dev/gpdf"
    "github.com/gpdf-dev/gpdf/document"
    "github.com/gpdf-dev/gpdf/pdf"
    "github.com/gpdf-dev/gpdf/template"
)

func main() {
    doc := gpdf.NewDocument(
        gpdf.WithPageSize(document.A4),
        gpdf.WithMargins(document.UniformEdges(document.Mm(20))),
    )

    page := doc.AddPage()
    page.AutoRow(func(r *template.RowBuilder) {
        r.Col(12, func(c *template.ColBuilder) {
            c.Text("청구서 #2026-0042", template.Bold(), template.FontSize(20))
            c.Spacer(document.Mm(6))
            c.Table(
                []string{"항목", "수량", "단가", "금액"},
                [][]string{
                    {"프론트엔드 개발", "40 시간", "₩200,000", "₩8,000,000"},
                    {"백엔드 개발",     "60 시간", "₩200,000", "₩12,000,000"},
                    {"UI 디자인",       "20 시간", "₩160,000", "₩3,200,000"},
                },
                template.ColumnWidths(50, 15, 15, 20),
                template.TableHeaderStyle(
                    template.Bold(),
                    template.TextColor(pdf.White),
                    template.BgColor(pdf.RGBHex(0x1A237E)),
                ),
            )
        })
    })

    data, err := doc.Generate()
    if err != nil {
        log.Fatal(err)
    }
    if err := os.WriteFile("invoice.pdf", data, 0o644); err != nil {
        log.Fatal(err)
    }
}

SetXY 0 개. 수동 컬럼 폭 계산 0 개. 문서 옵션에 gpdf.WithFont("NotoSansKR", ttfBytes) 를 더하면 위 한국어가 그대로 렌더링된다. 두부 현상 없음.

싣지 않은 것

모든 비교 글에는 "X 때문에 제외" 섹션이 있다. 우리 쪽:

  • 사내 gofpdf 포크. 프로덕션에서 돌고 있는 비공개 포크가 있다. 볼 수 없는 코드는 벤치할 수 없다.
  • pdfcpu. "Go PDF 라이브러리" 목록에 늘 보이지만 주 용도는 PDF 프로세서 (병합·분할·암호화·스탬프) 로 생성이 아니다. 이 글 범위 밖; 프로세싱 지향 별도 글을 계획.
  • gotenberg 이나 headless 브라우저 서비스 래퍼. 라이브러리가 아니고 공평한 비교도 아니다.
  • 자체 gpdf 벤치. 비교의 초점은 코어 수치.

FAQ

gpdf 는 왜 gofpdf 보다 10× 빠른가? 어떤 트릭? 단일 트릭은 없다. 3 가지 설계가 누적: 단일 패스 레이아웃 (빌더-라이터 간 AST 없음), 핫패스의 구체 타입, cmap 을 캐시하는 TrueType 서브세터. 하나당 2× 가량 기여. 누적해서 자릿수가 바뀐다.

이 벤치 직접 재현 가능한가? 가능. git clone https://github.com/gpdf-dev/gpdf && cd gpdf/_benchmark && go test -bench=. -benchmem. 같은 CPU 아키, 같은 Go 버전에서 숫자가 안 맞으면 이슈를 열어 달라. 벤치 드리프트는 발생하고 알고 싶다.

gofpdf 는 돌아오나? 현실적으로는 아니다. 마지막 커밋은 2021 년. 이슈 트래커는 닫혔다. 누가 다시 열어도 커서 + 싱글바이트 폰트 + 그리드 없음 의 아키텍처는 2026 년 출발점으로 맞지 않는다. 유물 취급 후 마이그레이션이 실용적.

Java iText / Python ReportLab / Node pdfkit 는? 언어 교차 벤치는 별도 글. 짧게: Go 는 처리량과 콜드스타트에서 대체로 이기고, 기능 폭 (특히 HTML→PDF 충실도) 에서 진다. 이미 Go 팀이면 gpdf 가 더 빠르고 작음. Python / Node 팀이 Go 로 옮길 땐 마이그레이션 비용이 커서 대용량일 때만 투자 회수.

경쟁사가 개선되면 이 비교는 공평성을 유지하나? 유지한다. 매년 돌린다. signintech/gopdf 가 테이블 API 를 내서 시간을 절반으로 줄이면 2027 판에 반영한다. Maroto v2 가 gofpdf 제거를 끝내면 그 행은 바뀐다. 벤치 코드를 공개한 건 어떤 누구도 우리 말을 믿을 필요 없게 하기 위해서다.

gpdf 써 보기

gpdf 는 Go 의 PDF 생성 라이브러리. MIT, 의존 0, 네이티브 CJK.

go get github.com/gpdf-dev/gpdf

⭐ GitHub 에서 스타 · 문서 읽기

이어서 읽기