- 코딩테스트
- Oracle
- boostcourse
- 네이버부스트캠프
- AI 플랫폼을 활용한 데이터 분석
- 파이썬
- 부스트코스
- PY4E
- 기초다지기
- 정보처리기사
- SQL
- 인공지능기초다지기
- 코딩테스트 python
- Django
- boostcoures
- Ai
- 빅데이터분석기사
- DB
- 이것이 취업을 위한 코딩테스트다 with 파이썬
- unsub
- 프로그래머스
- r
- 오라클
- 빅데이터 분석 기반 에너지 운영 관리자 양성 및 취업과정
- 이기적
- [멀티잇]데이터 시각화&분석 취업캠프(Python)
- 데이터베이스
- python
- 빅분기
- 데이터 분석 기반 에너지 운영 관리자 양성 및 취업과정
- Today
- Total
매일공부
[Django+WeasyPrint] PDF 템플릿만 CSS가 인라인인 이유 본문
궁금했던 것
일반 화면 템플릿들은 다 base.html을 상속하고 <link href="{% static '...css' %}">로 외부 CSS 파일을 불러오는데, PDF 생성용 템플릿(quotation_pdf.html 같은) 하나만 <style> 태그 안에 CSS가 통째로 인라인되어 있었다. 왜 이 파일만 다른 방식을 쓰는지 궁금해서 물어봤다.
확인
grep -c "<style>" templates/quotation/quotation_detail.html templates/brands/brand_form.html
# 결과: 둘 다 0
grep -rn "static.*\.css\|{% static" templates/base.html
# base.html은 <link rel="stylesheet" href="{% static 'css/design-system.css' %}" /> 로 외부 CSS를 불러옴
일반 페이지 템플릿들은 예상대로 <style> 없이 base.html이 불러오는 공통 CSS를 그대로 쓰고 있었다. PDF 템플릿만 유별났다.
원인 — 렌더링 경로 자체가 다르다
PDF 템플릿은 {% extends "base.html" %}을 아예 안 쓰고 <html>부터 완전히 독립된 문서로 만들어져 있다. 이유는 누가 이 HTML을 렌더링하는지가 다르기 때문이다.
- 일반 페이지: 브라우저가 서버에 HTTP 요청을 보내서 HTML을 받고, <link href="{% static ... %}">로 걸린 CSS도 브라우저가 별도 요청으로 가져와서 적용한다
- PDF: 브라우저를 아예 거치지 않는다. Django가 render_to_string()으로 만든 HTML 문자열을 그대로 WeasyPrint(HTML(string=...).write_pdf())에 넘겨서, 서버 프로세스 안에서 바로 PDF로 그려낸다
이 방식에서 만약 <link rel="stylesheet" href="{% static '...' %}">처럼 외부 CSS 파일을 참조하면, WeasyPrint가 그 CSS를 가져오기 위해 자체적으로 별도 요청을 해야 한다 — 그 시점에 정적 파일 서빙이 정상 동작해야 하고, base_url 설정도 정확히 맞아야 한다. (같은 문서 안에서 로고/직인 이미지를 file:// 절대경로로 넣는 것도 같은 이유다 — 외부 리소스 접근이라는 추가 의존성 자체를 없애는 게 안전하기 때문.)
CSS를 통째로 인라인해두면, WeasyPrint 입장에서는 외부 요청 없이 그 자리에서 바로 렌더링할 수 있어서 PDF 생성 파이프라인이 훨씬 안정적이다.
정리
"이 파일만 유별나게 인라인"인 게 아니라, 브라우저 없이 서버에서 직접 PDF로 렌더링하는 문서라서 외부 리소스 참조 자체를 피하는 게 원칙이다. base.html을 상속하는 일반 화면 템플릿들과는 애초에 성격이 다른 파일이다.
같은 맥락에서 정리하면:
일반 화면 템플릿 PDF 템플릿
| 렌더링 주체 | 브라우저 | 서버(WeasyPrint) |
| CSS | 외부 파일 링크 ({% static %}) | <style> 인라인 |
| 이미지 경로 | 웹 URL (/media/...) | 파일시스템 절대경로 (file://...) |
| base 템플릿 상속 | 함 (base.html) | 안 함, 독립 문서 |
서버 사이드에서 곧바로 PDF/이미지 등을 렌더링하는 템플릿을 만들 일이 있으면, "브라우저가 나중에 채워줄 거라고 가정하는 리소스"(외부 CSS, 웹 경로 이미지 등)는 전부 그 자리에서 바로 해결 가능한 형태(인라인 CSS, 절대경로)로 바꿔야 한다는 걸 이번에 확실히 배웠다.
'IT > 작업기록' 카테고리의 다른 글
| 시놀로지 NAS + 라우터로 내부 서비스에 서브도메인 연결하기 (IP:포트 대신 도메인으로 접속하기) (0) | 2026.08.20 |
|---|---|
| [DB] 개발 DB 민감정보 마스킹하기 — 어디까지, 어떻게 (0) | 2026.08.19 |
| [Git] 새 브랜치로 만든 기능, 테스트부터 dev 실반영까지 (0) | 2026.08.18 |
| [개발 회고록/Django] 판매지원 시스템, v1.0에서 v2.1까지 (0) | 2026.08.14 |
| [Git] dev/prod 배포 구조가 비대칭이었던 걸 온보딩 문서 쓰다가 발견한 이야기 (0) | 2026.08.12 |