AI자동화HTMLPDF셸스크립트

이력서를 AI한테 바로 PDF로 만들어 달라고 하지 않는 이유

2026년 10월 8일4 분 읽기

PDF를 바로 만들어 달라고 하면 안 되는 이유

해외 지원용 이력서를 준비하면서 PDF 파일이 필요했다. AI 코딩 에이전트에게 "이력서 PDF 만들어줘"라고 바로 시킬 수도 있었는데, 그렇게 하지 않았다. 대신 이렇게 2단계로 나눴다.

1단계: AI에게 이력서 내용을 HTML + CSS로 작성시킨다
2단계: 완성된 HTML을 headless Chrome으로 PDF 변환한다 (스크립트 1회 실행)

이렇게 나눈 이유는 단순하다. AI가 진짜 잘하는 건 HTML/CSS를 쓰는 것이지, PDF 바이너리를 직접 다루는 게 아니다. PDF를 바로 요청하면 AI는 결국 내부적으로 reportlab이나 weasyprint 같은 PDF 생성 라이브러리를 코드로 호출하거나, 자기도 똑같이 HTML을 거쳐서 변환하는 스크립트를 짜게 된다. 어차피 거칠 단계라면, 그 중간 산출물(HTML)을 내가 직접 받아서 확인하고 고칠 수 있게 만드는 게 낫다고 판단했다.

토큰을 아끼는 지점은 "생성"이 아니라 "재협상"이다

이력서는 한 번에 완성되지 않는다. 문구 하나, 여백 하나, 줄바꿈 위치 하나를 보면서 계속 고친다. PDF를 결과물로 받는 구조였다면, 이 수정 하나하나가 전부 AI에게 다시 "이 부분 조금 왼쪽으로", "이 줄 간격 좁게" 같은 요청으로 들어가야 한다. 매번 AI가 PDF 생성 로직 전체를 다시 추론하고 다시 실행해야 하니, 작은 수정 하나에도 꽤 많은 토큰이 든다.

HTML을 중간 산출물로 받으면 얘기가 달라진다. 폰트 크기나 여백처럼 뻔한 수정은 CSS 숫자 하나만 바꾸면 되고, 그마저도 AI 없이 내가 직접 에디터에서 고칠 수 있다. AI에게 다시 물어보는 건 "이 문단을 더 간결하게 써줘" 같은, 진짜 AI가 필요한 작업만 남는다. 변환은 스크립트 한 번 더 돌리면 끝이라 비용이 거의 안 든다.

실제로 쓴 스크립트

변환은 make_pdf.sh라는 셸 스크립트 하나로 끝낸다.

#!/bin/bash
cd "$(dirname "$0")"
SRC="HyunseokYu_ICT_Support_Engineer_CV.html"
OUT="../HyunseokYu_ICT_Support_Engineer_CV.pdf"
CHROME="/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"

rm -f "$OUT"
"$CHROME" --headless --disable-gpu --no-pdf-header-footer \
  --print-to-pdf="$(cd .. && pwd)/HyunseokYu_ICT_Support_Engineer_CV.pdf" \
  --print-to-pdf-no-header --virtual-time-budget=4000 \
  "file://$PWD/$SRC" >/dev/null 2>&1

핵심은 이 네 줄이다. 별도 변환 서비스나 유료 API 없이, 맥에 이미 깔려 있는 크롬을 headless 모드로 띄워서 "인쇄 → PDF로 저장"을 커맨드라인에서 그대로 재현한다. 브라우저가 렌더링하는 그대로 PDF가 나오니, 화면에서 본 레이아웃과 결과물이 어긋날 일이 없다.

플래그 하나씩 뜯어보면

플래그역할빼먹으면 생기는 문제
--headless --disable-gpu화면 없이 백그라운드로 크롬 실행창이 뜨거나 GPU 관련 에러로 실패
--print-to-pdf=경로지정한 경로에 PDF로 저장결과물이 생성되지 않음
--no-pdf-header-footer / --print-to-pdf-no-header크롬 기본 인쇄 머리말·꼬리말 제거file:///Users/... 경로와 날짜가 모든 페이지 상단에 찍힘
--virtual-time-budget=4000렌더링에 4초의 가상 시간을 줌웹폰트나 CSS가 덜 로드된 상태로 캡처될 수 있음

이 중에서 처음에 제일 많이 놓치는 게 --no-pdf-header-footer다. 이 플래그 없이 그냥 --print-to-pdf만 쓰면, 크롬이 일반 웹페이지를 인쇄할 때처럼 모든 페이지 위아래에 파일 경로와 날짜를 작게 찍어 넣는다. 이력서 맨 위에 file:///Users/hs/Documents/.../HyunseokYu_ICT_Support_Engineer_CV.html같은 로컬 경로가 그대로 노출되는 걸 처음 보고 당황했었다.

--virtual-time-budget도 은근히 중요하다. 헤드리스 크롬은 페이지를 열자마자 바로 캡처를 시도할 수 있는데, 웹폰트 로딩이나 레이아웃 계산이 끝나기 전에 찍히면 기본 폰트로 깨진 PDF가 나온다. 4초 정도 여유를 주는 것만으로 이 문제가 사라졌다.

사실 이 패턴을 쓴 게 이번이 처음은 아니다

돌이켜보면 똑같은 구조를 포트폴리오 PDF를 만들 때도 썼다. 그때는 Playwright로 HTML을 렌더링해서 page.pdf()로 변환했는데, 방식만 다를 뿐 "HTML을 먼저 완성하고, 그걸 결정론적으로 PDF로 찍어낸다"는 핵심 아이디어는 동일하다. 그때 추가로 겪은 문제가 하나 있는데, 이미지가 많은 문서라 PDF 용량이 지원 양식의 업로드 제한(10MB)을 넘겨버린 거였다. 이것도 AI에게 "PDF 용량 줄여줘"라고 다시 시키는 대신, HTML 안의 이미지 파일들을 직접 리사이즈·재압축한 뒤 같은 변환 스크립트를 한 번 더 돌리는 걸로 해결했다. 변환 단계가 분리돼 있으니 원인(이미지 용량)과 해결(이미지만 교체)이 둘 다 명확했다.

정리하면

AI 에이전트에게 결과물을 바로 달라고 하는 것과, 사람이 검수·수정할 수 있는 중간 형태를 거쳐서 받는 것 사이에는 생각보다 큰 차이가 있다. PDF처럼 사람이 직접 편집하기 어려운 최종 산출물을 바로 요청하면, 수정 한 번 한 번이 전부 AI를 다시 거쳐야 하는 작업이 된다. 반면 HTML처럼 사람도 읽고 고칠 수 있는 중간 형식을 거치면, 간단한 수정은 내가 직접 처리하고 AI는 정말 AI가 필요한 부분에만 쓰게 된다. 변환 자체는 headless Chrome 같은 도구로 스크립트 한 번이면 끝나니, 반복 비용도 거의 들지 않는다. "AI에게 최종 결과물을 바로 맡기기보다, 검수 가능한 중간 산출물을 거치게 한다"는 원칙은 이력서 PDF 말고도 꽤 여러 곳에 그대로 적용할 수 있을 것 같다.

PM

backtodev

40대 PM, 다시 개발자로 돌아갑니다. 실패하고 배우며 성장하는 기록.