기본 콘텐츠로 건너뛰기

[2025-07-28] python 에서 html to pdf 변환 비교

[2025-07-28] python 에서 html to pdf 변환 비교

안녕하세요. 클스 입니다.


html로 작성된 문서를 RAG를 하기위해서 html을 그대로 사용해도 되지만, 불필요한 테그가 있어 비효율 적입니다. 그렇다고 테그를 제거하면 표 등 레이아웃이 깨지게 됩니다.

일반적으로  pdf가 많이 사용됩니다. 그래서 macos에서 많이 사용하는 2개의 라이브러리를 비교해보고자 합니다.

1. html 을 바로 변환하는 방법 : weasyprint    [장점] 가볍다.

2. html 을 브라우저로 열어서 변환하는 방법 : playwright  
   [장점] 풍부하게 css를 처리한다.

코드

###### html to pdf #########
'''
외부망에서 해야 함
brew install pango
uv pip install weasyprint
'''
from weasyprint import HTML

html_file = '~/doc/test.html'
# 1. 문자열 경로를 Path 객체로 만듭니다.
path_obj = Path(html_file)
# 2. .with_suffix() 메서드로 확장자를 변경합니다.
pdf_file = path_obj.with_suffix('.pdf')
HTML(filename=html_file).write_pdf(pdf_file)


'''
외부망에서 해야함.
# 1. Playwright 라이브러리 설치
uv pip install playwright

# 2. Playwright가 제어할 브라우저(Chromium 등) 설치 (라이브러리 엄청 크네)
python -m playwright install
'''


import asyncio
from pathlib import Path
from playwright.async_api import async_playwright

async def convert_local_html_to_pdf_async(html_file_path: str, output_pdf_path: str):
"""
(비동기) 로컬 HTML 파일을 Playwright를 사용하여 PDF 파일로 변환합니다.
IPython/Jupyter 환경에 최적화되었습니다.

:param html_file_path: 변환할 원본 HTML 파일의 전체 경로
:param output_pdf_path: 저장할 PDF 파일의 전체 경로
"""
# pathlib.Path를 사용하여 파일 경로를 브라우저가 인식하는 file:// URI 형식으로 변환합니다.
# 이렇게 하면 공백이나 한글 등 특수문자가 포함된 경로도 안전하게 처리됩니다.
html_file_uri = Path(html_file_path).as_uri()
print("Playwright를 시작합니다...")
# 'async with'를 사용하여 비동기 컨텍스트 매니저를 실행합니다.
async with async_playwright() as p:
# 모든 I/O 작업(네트워크, 파일 시스템 등) 앞에 'await' 키워드를 붙여줍니다.
browser = await p.chromium.launch()
page = await browser.new_page()
try:
print(f"HTML 파일 로딩 중: {html_file_uri}")
# 페이지로 이동하고 로딩이 끝날 때까지 기다립니다.
await page.goto(html_file_uri)

print(f"PDF 파일 생성 중: {output_pdf_path}")
# PDF 생성이 완료될 때까지 기다립니다.
await page.pdf(
path=output_pdf_path,
print_background=True, # 배경 그래픽(색상, 이미지 등) 인쇄
format='A4' # 용지 형식 지정
)
print(f"✅ 성공: '{output_pdf_path}' 파일이 생성되었습니다.")

except Exception as e:
print(f"❌ 오류 발생: {e}")
finally:
print("브라우저를 닫습니다.")
# 브라우저 종료가 완료될 때까지 기다립니다.
await browser.close()

async def main():
"""
비동기 작업을 실행하기 위한 메인 함수
"""
# 1. 변환할 원본 HTML 파일 경로를 설정하세요.
'~/doc/test.html'

# 2. 저장할 PDF 파일 이름을 자동으로 설정합니다 (확장자만 .pdf로 변경).
output_file = Path(html_file).with_suffix('.pdf')

# 3. 위에서 정의한 비동기 변환 함수를 호출합니다.
await convert_local_html_to_pdf_async(html_file, str(output_file))


# IPython/Jupyter 환경에서는 'await'를 직접 사용하여 비동기 함수를 실행할 수 있습니다.
await main()


결론

둘다 레이아웃의 깨짐 없이 잘 변환해준다. 내가 선택하려면 자동화를 위해서 1번을 선택하는것이 맞다.

또 하나는 결과 파일의 크기 이다.

1) 51KB

2) 520KB


이상 클스 였습니다.


댓글

이 블로그의 인기 게시물

[quaser.dev][2014-09-14] 윈도우즈(10, 64bit)에 개발환경 설정하기

[quaser.dev][2014-09-14] 윈도우즈(10, 64bit)에 개발환경 설정하기

[2024-10-19] iPhone, iPad에서 ChatGPT로 PDF 생성시 한글 깨짐 해결 방법

iPhone, iPad에서 ChatGPT로 PDF 생성 시 한글 깨짐 해결 방법

[2025-04-16(수)] OpenAI gpt-4.1 시리즈 발표, Anthropic Claude에 대한 생각

OpenAI gpt-4.1 시리즈 발표, Anthropic Claude에 대한 생각 안녕하세요. 클스 입니다. 4/15일자로 openai가 gpt-4.1 시리즈를 발표 했습니다. 현재는 api로만 사용가능합니다. 점차 웹/앱 사용자에게 오픈 될거라 생각 됩니다. 비용상 문제로 4.1-mini, nano를 사용해서 chatbot을 만들어 보고 있습니다. 4o 시리즈 보다는 확실히 빠르고, 답변의 정확도는 올라간 것 같습니다. 앤트로픽 클로드와 비교를 많이 하는데, 업무 시스템 혹은 AI 솔루션을 개발하는 입장에서는 어떤 생태계를 제공하는가가 주요한 결정 입니다. AI관련 인력을 충분히 보유한 회사의 경우는 어떤걸 사용해도 좋을 결과를 가지겠지만 일반적인 챗봇 개발 절차를 보면 다음과 같이 볼 수 있습니다. 1. 문서를 준비한다. 대부분 pdf, text, markdown 2. 문서를 파싱해서 vectordb에 올린다.     - 별도 벡터디비 구성 필요. 어떤 db를 선택할지 고민 필요     - 어떤 Parser를 사용할지, 텍스트 오버래핑은 얼마가 적당한지 고민 필요        (회사의 문서가 워낙 많고, 다양하면 하나하나 테스트 해서 좋은걸 선택하는 것이 어렵다)     - 유사도 측정은 어떤 알고리즘을 써야할지 고민 필요     - llamaindex도 고민해야 함. 3. RAG flow를 만든다.     - langchain을 쓸지, 각 AI 벤더에서 제공하는 sdk를 쓸지 고민 필요       (대부분 락인이 되지 않으려면 langchain을 사용하면 좋지만, 벤더에 특화면 기능 적용이 늦음) 4. 챗봇 UI 앱을 만든다.     - 답변이 text 로 구성되다 보니. 그래프, 이미지등 복합적인 컨텐츠를 재배치 하여 표현하기 상당히 어렵네요. (이건 제가 실력이 모자라서 .. 패스) ...