- Published on
axum rust pdf: Axum에서 PDF 응답 설계하기
- Authors

- Name
- Indo Yoon
axum rust pdf를 찾는 경우는 Axum 자체에 PDF 생성 기능이 있다고 기대하기보다, PDF를 만들어 HTTP 응답으로 안전하게 내보내는 방법을 알고 싶을 때가 많습니다. Axum은 웹 프레임워크이고 PDF 생성은 별도 라이브러리나 외부 렌더러의 역할로 나누는 편이 유지보수에 유리합니다. 이 글은 공식 문서에서 확인할 수 있는 Axum의 라우팅·응답·미들웨어 개념을 기준으로 PDF 제공 절차를 정리합니다.
한눈에 보기
Axum에서 PDF를 다룰 때 가장 중요한 구분은 “PDF를 만드는 일”과 “PDF를 전송하는 일”입니다. Axum 공식 문서는 Axum을 Tokio와 Tower 생태계 위에서 동작하는 웹 프레임워크로 설명하며, PDF 생성 API를 별도로 제공하지 않습니다. 따라서 PDF 생성은 Rust 크레이트, 외부 렌더링 서비스, 사전 생성된 파일 저장소 같은 경로로 처리하고 Axum은 라우팅과 응답에 집중하게 만드는 것이 자연스럽습니다.
- 라우팅과 인증은 Axum의 핸들러와 미들웨어에서 처리합니다.
- PDF 생성은 전용 크레이트나 외부 작업 큐로 분리합니다.
- 응답 본문은 바이트, 스트림, 정적 파일 제공 중 상황에 맞게 고릅니다.
Content-Type,Content-Disposition, 캐시 헤더를 명시적으로 설계합니다.- 생성 비용이 큰 작업은 비동기 런타임을 막지 않도록 분리합니다.
Axum과 PDF 처리 역할 비교
| 구분 | Axum이 맡는 일 | PDF 쪽에서 결정할 일 | 운영 시 확인할 점 |
|---|---|---|---|
| 라우팅 | 경로와 메서드 정의, 핸들러 연결 | 문서 식별자와 생성 요청 구분 | 권한 검사 위치와 경로 충돌 |
| 생성 | 생성 작업을 호출하거나 큐에 위임 | 라이브러리, 템플릿, 폰트, 이미지 처리 | 실패 재시도와 작업 상태 관리 |
| 응답 | 헤더와 본문 반환 | 바이트 크기, 스트리밍 가능 여부 | 메모리 사용량과 타임아웃 |
| 정적 파일 | 라우트에서 파일 제공기로 위임 | 파일 저장 위치와 이름 규칙 | 캐시, 범위 요청, 접근 제어 |
| 보안 | 인증·인가 미들웨어 적용 | 민감 정보 포함 여부 | 파일명 정규화와 헤더 인젝션 방지 |
| 관측 | 로그, 추적, 오류 응답 | 생성 시간과 실패 원인 기록 | 사용자별 남용 탐지와 감사 로그 |
단계별 구현 방법
라우트와 핸들러를 분리합니다
먼저 PDF 다운로드 경로와 생성 요청 경로를 분리하는 것이 좋습니다. 예를 들어 문서 식별자를 받는 다운로드 경로와, 생성 작업을 시작하는 경로를 나누면 권한 검사와 캐시 정책을 각각 다르게 가져갈 수 있습니다. Axum의 라우터는 경로와 핸들러를 명시적으로 연결하므로, 핸들러 안에서 생성과 전송을 한꺼번에 처리하기보다 서비스 계층을 호출하도록 구조를 잡습니다.
PDF 바이트를 응답으로 감쌉니다
이미 만들어진 PDF를 메모리에 올릴 수 있는 상황이라면 바이트 본문과 헤더를 함께 반환하는 방식이 단순합니다. Axum은 IntoResponse를 구현한 타입을 핸들러 반환값으로 사용할 수 있으므로, 헤더 배열과 바이트 본문을 조합해 응답으로 만들 수 있습니다. 이때 본문 타입과 헤더 타입이 Axum이 기대하는 형태인지 공식 문서의 응답 예제를 기준으로 확인합니다.
헤더를 명시합니다
PDF 응답에는 Content-Type: application/pdf를 지정하고, 다운로드인지 미리보기인지에 따라 Content-Disposition을 다르게 둡니다. 파일명을 사용자 입력에서 가져온다면 경로 구분자, 줄바꿈, 제어 문자를 제거하거나 허용 문자만 남기는 정규화가 필요합니다. 캐시를 허용할 문서인지, 사용자별 비공개 문서인지에 따라 Cache-Control 정책도 함께 정해야 합니다.
큰 파일은 스트리밍을 검토합니다
PDF가 커질 수 있는 서비스라면 전체 파일을 메모리에 올리는 방식이 부담이 될 수 있습니다. Axum의 응답 본문은 바이트뿐 아니라 스트림을 담는 형태로 구성할 수 있으므로, 생성 라이브러리가 스트리밍을 지원하는지 먼저 확인합니다. 이미 저장된 정적 PDF라면 tower-http의 ServeFile이나 ServeDir에 제공을 위임해 파일 제공 로직을 직접 구현하는 범위를 줄일 수 있습니다.
생성 작업은 비동기 런타임 밖으로 분리합니다
PDF 생성은 폰트 처리, 이미지 압축, 레이아웃 계산 때문에 CPU를 오래 사용할 수 있습니다. Tokio 공식 문서는 블로킹 작업을 spawn_blocking으로 분리하도록 안내하므로, 요청 핸들러에서 무거운 동기 작업을 그대로 실행하지 않도록 주의합니다. 생성 시간이 길어질 수 있는 작업은 작업 큐와 상태 조회 경로를 두는 편이 안정적입니다.
테스트는 헤더와 본문을 함께 확인합니다
PDF 응답 테스트에서는 상태 코드만 보지 말고 Content-Type, Content-Disposition, 캐시 헤더를 함께 확인합니다. 본문은 PDF 시그니처와 길이를 검사하되, 생성 라이브러리의 출력이 달라질 수 있는 부분은 고정된 바이트 비교보다 구조적 검증이 낫습니다. 인증이 필요한 경로라면 권한이 없는 사용자가 파일을 받을 수 없는지도 별도로 확인합니다.
상황별 선택 기준
작은 PDF를 요청마다 즉시 만들고 응답한다면 메모리 바이트 응답이 구현하기 쉽습니다. 반면 미리 만들어진 약관, 보고서, 안내문처럼 내용이 자주 바뀌지 않는 PDF는 정적 파일로 두고 ServeFile로 제공하는 편이 단순합니다. 사용자별로 큰 PDF를 생성한다면 생성 작업을 큐에 넣고, 완료된 파일을 임시 저장소나 오브젝트 스토리지에서 스트리밍하는 구조를 검토합니다.
HTML 템플릿을 PDF로 바꾸는 요구가 있다면 Axum 안에서 모든 변환을 처리하기보다 외부 렌더러나 별도 작업 프로세스로 분리하는 것이 장애 격리에 유리합니다. 이때 Axum은 작업 요청을 접수하고 상태를 조회하며, 완료된 파일에 대한 인증된 다운로드 경로를 제공하는 역할로 제한할 수 있습니다. 어떤 방식을 택하든 PDF 생성 실패와 전송 실패를 구분해 로그에 남기는 것이 운영에 도움이 됩니다.
주의할 점
PDF 파일명을 그대로 Content-Disposition에 넣으면 헤더 인젝션 위험이 생길 수 있습니다. 사용자 입력에서 파일명을 받는 경우 허용 문자만 남기고, 경로 이동 문자가 들어가지 않도록 정규화한 뒤 사용합니다. 또한 인증된 사용자만 접근할 수 있는 문서라면 라우트 수준의 인가 검사와 저장소 수준의 접근 제어를 함께 적용해야 합니다.
PDF 생성은 실패 지점이 많은 작업입니다. 폰트 누락, 이미지 형식 오류, 템플릿 데이터 불일치, 저장 공간 부족 같은 문제를 사용자 오류와 구분해 기록해야 합니다. 생성 작업을 재시도할 때는 같은 요청이 중복 생성되지 않도록 작업 식별자를 두고, 완료된 파일의 캐시 무효화 정책도 함께 정합니다.
비동기 핸들러 안에서 무거운 동기 PDF 생성을 직접 호출하면 다른 요청의 처리 지연으로 이어질 수 있습니다. Tokio의 블로킹 작업 지침을 참고해 생성 작업을 분리하고, 생성 시간이 길어지는 경우에는 요청-응답 방식보다 작업 큐 방식이 적합한지 검토합니다. 운영 환경에서는 생성 실패율, 대기 시간, 파일 제공 오류를 관찰할 수 있도록 로그와 지표를 남기는 것이 좋습니다.
자주 묻는 질문
질문: Axum에 PDF 생성 기능이 내장되어 있나요?
아니요. Axum은 웹 요청을 라우팅하고 응답을 구성하는 프레임워크이며, 공식 문서에서도 PDF 생성 전용 API를 안내하지 않습니다. PDF 생성은 Rust PDF 크레이트나 외부 렌더러, 사전 생성된 파일 저장소 같은 별도 수단으로 처리해야 합니다. Axum은 그 결과를 HTTP 응답으로 안전하게 전달하는 역할에 집중하게 만드는 편이 좋습니다.
질문: PDF를 메모리에 올리지 않고 스트리밍할 수 있나요?
가능합니다. Axum의 응답 본문은 바이트 형태뿐 아니라 스트림 형태로도 구성할 수 있고, 저장된 정적 파일은 tower-http의 파일 제공 기능에 위임할 수 있습니다. 다만 사용하는 PDF 생성 라이브러리가 스트리밍 출력이나 임시 파일 출력을 지원하는지 먼저 확인해야 합니다.
질문: PDF 다운로드 파일명은 어떻게 지정하나요?
Content-Disposition 응답 헤더의 filename 파라미터로 지정합니다. 사용자 입력을 그대로 넣지 말고 허용 문자로 정규화한 파일명을 사용하며, 미리보기와 다운로드를 구분하려면 inline과 attachment 중 어떤 방식을 쓸지 정해야 합니다. 파일명에 경로 구분자나 제어 문자가 들어가지 않도록 검증하는 절차도 함께 두는 것이 안전합니다.
출처
- Axum 공식 문서: https://docs.rs/axum/latest/axum/
- Axum 공식 저장소: https://github.com/tokio-rs/axum
- tower-http 공식 문서: https://docs.rs/tower-http/latest/tower_http/
- Tokio
spawn_blocking공식 문서: https://docs.rs/tokio/latest/tokio/task/fn.spawn_blocking.html
관련 운영 글: Rust 서버 배포와 운영 체크리스트에서 PDF 생성 작업을 별도 프로세스로 분리할 때의 배포 구조와 장애 대응 관점을 함께 확인해 보세요.