10분 만에 100만 개의 PDF 생성하기
(ersteiger.com)- 금융업계에서의 대규모 PDF 생성 요구사항을 해결하기 위해, Rust와 Typst 기반 서버리스 아키텍처를 구축한 사례
- AWS Lambda, SQS, S3, API Gateway를 활용하여 1,667개/초의 렌더링 목표를 설정하고, 병렬성과 캐싱 최적화를 통해 성능 향상
- 기존 방식(Puppeteer, LaTeX 등)의 병목을 해결하기 위해 경량화된 Typst 렌더러와 Papermake 라이브러리를 활용함
- 템플릿 캐싱, world 캐싱, SQS 배치 처리 등으로 1건당 평균 35ms까지 속도 단축, 단가도 0.35유로로 절감
- 실서비스 적용을 위해 모니터링, 서명/암호화, 다중 리전 배포 등의 추가 고려사항도 제시
Making millions in minutes, why?
- 금융 업계에서는 수백만 건의 거래 확인서 및 세금 관련 문서를 수 분 내로 생성해야 하는 요구가 존재함
- 지연 시 BaFin 등 감독기관에 의해 벌금 부과 위험이 있음
- 목표는 10분 안에 100만 개의 PDF 생성, 초당 1,667개, PDF당 약 0.6ms 소요 필요
Architecture Decisions
- Rust와 AWS Lambda, SQS, S3, API Gateway 기반의 서버리스 아키텍처 사용
- 각 구성 요소:
- API Gateway: 외부 요청을 수신
- SQS: PDF 렌더링 작업 큐
- Lambda 함수: 요청 처리 및 PDF 렌더링
- S3: 템플릿과 결과 PDF 저장
New Rendering Technology
- 기존 PDF 생성 도구들은 느림:
- Puppeteer: 1~2초
- Crystal Reports: 750~900ms
- LaTeX: 500~800ms
- 새로운 Typst는 빠르면서도 문서 오류 메시지를 잘 제공
- Typst를 활용한 Papermake 라이브러리 개발, 데이터 기반 렌더링 지원
Creating the template
- Papermake 템플릿 구조는 frontmatter + Typst 마크업으로 구성됨
- 변수
#data.customer.name
등의 형태로 데이터 삽입 - 예시 템플릿은 MoneyBank의 거래 확인서이며, 고객 정보 및 거래 상세 내용을 포함함
Implementing our two lambda functions
- 두 개의 Lambda 함수는 Rust로 작성됨
- Request Handler: API Gateway에서 요청을 받아 SQS에 렌더링 작업 전송
- Renderer: SQS에서 작업을 받아 PDF를 생성하고 S3에 업로드
- Rust는 cold start가 거의 없고 네이티브 컴파일러라 빠름
- Typst + Papermake로 PDF를 생성, S3에 결과 저장
Terraform definition
- 전체 인프라는 Terraform으로 IaC 구현, 관리 효율성 극대화
- 주요 리소스:
- S3: 템플릿 저장소 및 결과 저장소
- SQS: 작업 큐
- Lambda 함수: request handler 및 renderer
- API Gateway: HTTP POST /render 엔드포인트
- Lambda 함수는 Amazon Linux 2023, arm64 아키텍처에서 실행됨
Performance Tuning
1. Lambda Concurrency
- 초당 1,667개 PDF를 처리하려면 최소 60개 이상의 병렬 인보케이션 필요
- Auto Scaling 정책을 통해 SQS 큐 깊이에 따라 Lambda 인스턴스를 동적으로 확장
2. Caching
- S3 요청, 템플릿 파싱, Typst world 컴파일 등은 공유 리소스로 캐싱하여 처리 속도 향상
-
OnceCell
및RwLock
을 활용해 핫스타트 상태에서 35ms 수준의 처리 속도 확보
3. Batching
- SQS의 배치 처리 기능을 통해 네트워크 오버헤드 감소 및 효율 향상
- 템플릿별로 데이터를 그룹핑하여 중복 템플릿 로딩 방지
Results
- 10개 병렬 Lambda 환경 기준:
- 처리 시간: 11초
- 초당 처리량: 91개
- 목표에는 미치지 못했지만, 병렬도만 높이면 도달 가능
- 렌더링 속도: 평균 34ms (캐싱 적용 후)
Cost calculation
- Lambda 단가 기준:
- 1백만 건 요청 시 총 비용 0.35유로
- 컴퓨팅: 0.15유로
- 호출 비용: 0.20유로
- 프리 티어 내에서 대부분 테스트 가능, 비용 효율 매우 우수함
Next Steps
- 실제 100만 개 렌더링 테스트를 위한 AWS 동시 호출 수 제한 해제 대기 중
- 실 서비스 적용 시 고려 사항:
- 템플릿 ID 기반 큐 라우팅
- 장애 감지 및 재시도 로직
- 다중 리전 배포
- 전자 서명 및 암호화 처리 등
마무리
- 본 프로젝트는 Rust와 Typst를 활용한 고성능 PDF 생성 파이프라인 구현 예제임
- 전체 코드: papermake-aws GitHub
- 렌더링 엔진: Typst, 렌더링 라이브러리: Papermake
금융 업계에서는 수백만 건의 거래 확인서 및 세금 관련 문서를 수 분 내로 생성해야 하는 요구가 존재함
지연 시 BaFin 등 감독기관에 의해 벌금 부과 위험이 있음
이런 요구가 왜 있는건지는 궁금하네요 ㅎㅎ
지표 단위를 일관적으로 적용하여 계산했습니다
목표: 1,666.7개/s
람다 10개 병렬처리: 29.4개/s, 람다 570개로 스케일 아웃시 목표 달성 가능
기존 PDF 생성 도구 (단일):
- Puppeteer: 0.5~1개/s
- Crystal Reports: 1.1~1.3개/s
- LaTeX: 1.2~2개/s