블로그 글을 자동으로 쓰는 건 됐는데, 이미지가 문제였습니다. 네이버 블로그는 썸네일이 없으면 유입에 직접적인 영향이 있고, 본문 이미지가 없으면 글이 너무 길어 보여서 이탈률이 올라갑니다. 텍스트는 LLM이 해결해줬지만 이미지는 다른 문제였습니다.


처음엔 그냥 넘어가려고 했습니다

스톡 이미지를 써도 되고, Stable Diffusion API를 붙일 수도 있었습니다. 근데 스톡 이미지는 매번 고르는 게 귀찮았고, SD API는 품질이 일정하지 않았습니다. 마침 Gemini의 이미지 생성 품질이 꽤 좋아졌다는 얘기를 들었는데, 막상 API로 쓰면 생성할 때마다 비용이 나갑니다. 블로그 글 하나에 이미지가 세 장이고 하루에 여러 글을 올리면 쌓이는 게 무시하기 어려웠습니다.

그래서 Playwright로 웹 UI를 직접 쓰기로 했습니다. 웹에서는 계정당 하루 일정 횟수까지 무료로 쓸 수 있으니까요.


생각보다 복잡했습니다

브라우저를 자동으로 열어서 프롬프트를 입력하고 이미지가 나오길 기다리는 건 원리는 단순한데, 실제로 만들어보니 신경 써야 할 게 생각보다 많았습니다.

완료 타이밍을 알 방법이 없다는 게 제일 까다로웠습니다. 이미지 생성이 언제 끝나는지 알려주는 이벤트 같은 게 없으니까, 페이지를 주기적으로 확인해서 새 이미지가 생겼는지 감지해야 했습니다. UI 요소들까지 카운트되면 안 되니까 필터 기준도 잡아야 했고요.

headless로 돌리면 안 된다는 것도 겪어봐야 알았습니다. 처음에 한참 안 되다가 원인 찾는 데 시간이 걸렸습니다. 결국 서버에 X 환경이 있어야 하고, systemd 서비스로 돌릴 때는 디스플레이 설정을 환경 변수로 명시해줘야 합니다. 이게 빠지면 에러 로그 없이 그냥 조용히 안 됩니다.


글 하나에 이미지가 세 개 필요합니다

썸네일, 본문 이미지 1, 본문 이미지 2. 처음엔 순서대로 생성했는데 다 합치면 꽤 오래 걸렸습니다. 그래서 계정을 여러 개 써서 동시에 돌리는 구조로 바꿨더니 시간이 많이 줄었습니다. 각 슬롯이 독립적으로 돌아가니까 하나가 실패해도 나머지에 영향을 주지 않는다는 것도 장점이었습니다.


프롬프트도 자동으로 만듭니다

이미지를 자동 생성한다면 프롬프트도 자동으로 나와야 의미가 있습니다. 글 제목과 키워드를 로컬 LLM에 넘기면 각 이미지에 어떤 내용을 담을지 제안해줍니다. “무엇을 그려야 하는지”에 집중해서 묘사하고, 스타일이나 비율 같은 기술적인 지시는 코드에서 붙이는 식으로 역할을 나눴습니다.

그 과정에서 한 가지 배운 게 있는데, 특정 단어를 프롬프트에 넣으면 Gemini가 이미지 안에 그 단어를 텍스트로 직접 써버리는 경우가 있었습니다. 원하지 않는 텍스트가 이미지에 들어오면 쓰기 어려워지기 때문에 프롬프트를 계속 다듬어야 했습니다. 반대로 썸네일에는 제목을 이미지에 넣고 싶을 때도 있어서, 텍스트 포함 여부는 별도로 제어할 수 있게 분리해뒀습니다.


결국 이것도 대시보드 안에 들어갔습니다

처음엔 커맨드라인에서 쓰다가 대시보드에 탭으로 들어갔습니다. 자동으로 만들어진 프롬프트가 마음에 안 들 때 수정할 수 있고, 이미지 하나만 다시 만들고 싶을 때 해당 슬롯만 재생성할 수 있습니다. 전체를 다시 돌리지 않아도 된다는 게 생각보다 자주 쓰입니다.


비용 문제를 우회하려다 만든 구조인데, 어쩌다 보니 꽤 잘 굴러가고 있습니다. 우아한 방법은 아닌 것 같지만, 지금은 이게 됩니다.