11P by neo 1일전 | ★ favorite | 댓글 3개
  • 금융업계에서의 대규모 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 컴파일 등은 공유 리소스로 캐싱하여 처리 속도 향상
  • OnceCellRwLock을 활용해 핫스타트 상태에서 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