
블로그 포스팅을 자동화하면 편해질 거라고 생각했습니다. 실제로 해보니 절반은 맞고 절반은 틀렸습니다. GPT-4o와 WordPress REST API를 이어붙여 350줄짜리 Python 파이프라인을 완성하기까지, 예상치 못한 곳에서 계속 발목이 잡혔습니다. 그 과정을 가감 없이 정리했습니다.
프롬프트 엔지니어링과 출력 포맷 일관성 확보
파이프라인을 처음 설계할 때 가장 오래 걸린 부분이 어디였냐고 물으면, 대부분 "OpenAI API 연결 아니냐"고 예상합니다. 그런데 직접 겪어보니 API 호출 자체는 30분이면 끝났습니다. 진짜 난관은 프롬프트 엔지니어링(Prompt Engineering)이었습니다. 프롬프트 엔지니어링이란 AI 모델이 원하는 형식과 품질의 결과를 일관성 있게 출력하도록 입력 지시문을 설계하는 작업을 의미합니다.
문제는 이랬습니다. GPT-4o에게 "2000자 분량의 블로그 글을 써라"고 지시하면, 어떤 요청에서는 마크다운 헤더가 붙어 나오고 다른 요청에서는 그냥 평문으로 출력됐습니다. 10번 돌리면 10번 다 조금씩 달랐습니다. 이 출력 포맷의 불일치는 이후 HTML 변환 단계에서 파싱 오류로 이어졌고, 파이프라인 전체가 중간에 멈추는 원인이 됐습니다.
해결책은 response_format 파라미터를 활용하는 것이었습니다. 여기서 response_format이란 OpenAI API에서 출력 형식을 강제하는 파라미터로, json_object로 설정하면 모델이 반드시 유효한 JSON 형태로만 응답하도록 제한할 수 있습니다. 시스템 프롬프트에 JSON 스키마 출력 지시를 명시하고, 이 파라미터를 함께 적용했더니 {"title": "...", "sections": [...], "meta_description": "..."} 구조가 매 요청마다 일관되게 나왔습니다. HTML 변환 코드가 눈에 띄게 단순해진 건 덤이었습니다.
WordPress REST API 연동에서는 예상치 못한 함정이 숨어 있었습니다. 포스트를 먼저 생성하고 나서 이미지를 붙이는 순서로 코드를 짰는데, 썸네일이 빠진 채 글이 올라가는 조용한 버그가 발생했습니다. 500 에러도 없었고, 로그상으로도 성공처럼 보였습니다. 원인을 파악하고 나서 올바른 순서로 수정했습니다.
올바른 이미지 업로드 순서는 다음과 같습니다.
- /wp/v2/media 엔드포인트에 이미지 파일을 먼저 업로드해 media ID를 발급받는다.
- 해당 media ID를 featured_media 필드에 포함한 페이로드로 포스트를 생성한다.
- Application Password 인증 헤더를 세션 객체에 등록해 이후 모든 요청에 재사용한다.
여기서 Application Password란 WordPress에서 REST API 인증을 위해 발급하는 전용 비밀번호로, 사용자 계정 비밀번호와 분리돼 있어 보안상 유리합니다. 이 순서를 뒤집으면 에러 없이도 featured image가 빠지는 케이스가 발생하므로, 반드시 미디어를 선 업로드하는 구조로 설계해야 합니다.
비용 최적화와 파이프라인 안정성 설계
비용 문제는 자동화를 실제 운영 단계까지 가져가면 반드시 마주치게 됩니다. 제가 직접 써봤는데, 처음에는 모든 단계를 GPT-4o로 처리했다가 월 API 청구서를 보고 멈칫했습니다. 그래서 단계별 모델 혼합 전략을 도입했습니다.
아이디어 초안 5개를 뽑는 단계는 GPT-4o-mini로 처리하고, 그 중 하나를 실제 글로 확장할 때만 GPT-4o를 사용하는 방식입니다. 월 300편 기준으로 API 비용이 약 40% 감소했습니다. 여기에 Batch API(배치 API)를 추가로 활용하면 비용을 더 줄일 수 있습니다. Batch API란 여러 요청을 묶어 비동기 방식으로 처리하는 OpenAI의 기능으로, 동일 작업 기준 비용이 최대 50% 절감됩니다(출처: OpenAI). 다만 처리 완료까지 최대 24시간이 걸리기 때문에 실시간 발행이 필요 없는 예약 발행 파이프라인에서만 쓸 수 있습니다.
운영 중 가장 곤란했던 사고는 스케줄러 문제였습니다. APScheduler를 사용해 발행 작업을 예약해두었는데, 서버가 재시작되자 대기 중이던 작업 큐 전체가 메모리에서 사라졌습니다. 솔직히 이건 예상 밖이었습니다. 며칠치 발행 스케줄이 한 번에 날아간 경험을 해보면, 상태 영속성(State Persistence)이 얼마나 중요한지 체감하게 됩니다. 상태 영속성이란 서버가 종료되거나 재시작되더라도 작업 상태가 유지되는 특성을 의미합니다.
해결책은 SQLAlchemy JobStore를 붙여 SQLite에 스케줄 상태를 저장하도록 수정하는 것이었습니다. 이후로는 서버가 재시작돼도 대기 중인 발행 작업이 그대로 살아났습니다. 이 경험을 통해 자동화 파이프라인은 처음 설계 단계부터 상태 저장 방식을 명시적으로 포함시켜야 한다는 걸 뼈저리게 느꼈습니다(출처: APScheduler).
품질 문제도 짚어야 합니다. GPT-4o는 hallucination(할루시네이션), 즉 사실이 아닌 정보를 그럴듯하게 생성하는 현상이 여전히 발생합니다. 통계 수치나 날짜처럼 팩트 검증이 필요한 요소를 파이프라인이 자동으로 걸러내지 못합니다. 자동화 도구를 사용하는 블로거와 수동 작성 블로거를 비교한 통계에서도 트래픽 성장률이 단순히 포스팅 빈도에 비례하지 않는다는 결과가 나옵니다(출처: Backlinko). 발행 속도가 빨라질수록 틀린 정보가 퍼지는 속도도 함께 올라간다는 역설입니다.
Google은 2023년 이후 AI 생성 콘텐츠 자체를 직접 제재하지는 않지만, Helpful Content Update를 통해 독자에게 유용하지 않은 저품질 콘텐츠의 검색 순위를 낮추고 있습니다. E-E-A-T(경험·전문성·권위성·신뢰성)를 중시하는 현재 알고리즘 하에서, 키워드만 넣고 완전히 AI에 맡기는 방식은 중장기적으로 도메인 전체의 신뢰도를 훼손할 수 있습니다. 제 경험상 이건 단기 포스팅 수에만 집중하면 반드시 나중에 후회하게 되는 지점입니다.
자동화는 초안 생성의 보조 수단으로 활용하고, 사람이 최종 검토하는 단계를 파이프라인 안에 명시적으로 넣어두는 설계가 지속 가능합니다. 또한 Python 환경 설정, API 키 관리, 서버 운영 등은 비기술 블로거에게 여전히 높은 진입 장벽입니다. Make나 n8n 같은 노코드 도구가 확산되는 이유가 여기 있으며, Python 파이프라인은 세밀한 제어가 필요한 중급 이상 사용자에게 적합합니다.
자동화 파이프라인의 완성도는 코드 줄 수가 아니라 운영 중에 얼마나 조용하게 돌아가느냐로 판가름됩니다. 처음 설계할 때 상태 영속성, 비용 구조, 품질 검증 단계까지 함께 고민해두면 나중에 같은 시행착오를 반복하지 않아도 됩니다. 당장 파이프라인을 구축하기 전에 어떤 단계에 사람이 반드시 개입해야 하는지를 먼저 정해두는 것, 그것이 제가 직접 부딪히며 얻은 가장 실용적인 결론입니다.
참고:
[1] OpenAI Platform Documentation — Chat Completions https://platform.openai.com/docs/api-reference/chat
[2] WordPress REST API Handbook — Creating Posts https://developer.wordpress.org/rest-api/reference/posts/
[3] APScheduler Documentation — Persistent Job Stores https://apscheduler.readthedocs.io/en/stable/userguide.html
[4] Google Search Central — AI-generated Content Guidance (2023) https://developers.google.com/search/docs/essentials/ai-generated-content
[5] Backlinko — Blogging Statistics Report 2024 https://backlinko.com/blogging-statistics
[6] OpenAI — Batch API Documentation https://platform.openai.com/docs/guides/batch