AI로 10개국어 블로그를 혼자 운영하는 방법 — 자동화 시스템 구축 전체 공개

2026. 3. 24. 10:43·IT · 테크/마케팅 · 수익화
반응형

 

PROJECT OVERVIEW

AI로 10개국어 블로그를 혼자 운영하는 방법

Claude AI + GPT-4o + WordPress REST API + Cloudflare R2로 구축한 다국어 콘텐츠 자동 발행 인프라. 아키텍처 설계부터 버그 수정, 브랜드 로고 제작, SEO 개선, 운영 리포트까지 — 구축 과정 전체를 공개합니다.

핵심 키워드: AI 콘텐츠 생성, WordPress 자동화, 다국어 SEO, Python 스케줄러


이 글의 순서

1. 왜 이 시스템을 만들었나 — 아이디어의 출발점

2. 전체 아키텍처 — 10개 서버, 10개 언어, 1개 코드베이스

3. AI 콘텐츠 생성 파이프라인 — Claude + GPT-4o 조합

4. 썸네일 자동 생성 — Pillow + AI 이미지

5. Cloudflare R2 이미지 호스팅 마이그레이션

6. 자동 발행 스케줄러 — FIFO 큐 + 랜덤 시간 배정

7. GitHub Actions CI/CD — 10개 서버 동시 배포

8. SEO 자동화 — Rank Math + 구조화 데이터

9. 발견하고 수정한 버그들

10. KWON 브랜드 로고 시스템 — Pillow로 10개 블로그 로고 제작

11. AI 소설 자동 발행 시스템 — 구현에서 폐기까지

12. 운영 리포트 시스템 — GA4 + GSC → HTML 자동 생성

13. 법적 페이지 + 마이그레이션 도구 6종

14. 서버 운영 도구 — sync.sh + LiteSpeed 자동화

15. 10개 블로그 SEO 전수검사 — 4단계 개선

16. Google Indexing API로 색인 가속화

17. 현재 성과와 앞으로의 계획


AI로 10개국어 블로그를 혼자 운영하는 자동화 시스템 개요


BACKGROUND

1. 왜 이 시스템을 만들었나

블로그로 수익을 내고 싶었습니다. 하지만 혼자서 10개 언어로 매일 포스트를 쓰는 건 사실상 불가능합니다. 그래서 생각을 바꿨습니다. "AI가 쓰면 되지 않나?"

처음에는 단순했습니다. 한국어 블로그 하나에 AI로 글을 생성하고 WordPress에 올리는 스크립트. 그런데 만들다 보니 욕심이 생겼습니다. 어차피 코드는 같은데, 언어만 다르게 하면 10개 블로그를 동시에 운영할 수 있지 않을까?

핵심 아이디어

하나의 Python 코드베이스 + 언어별 설정 파일 = 10개 다국어 블로그 동시 운영. 서버는 언어별로 개별 Vultr VPS를 사용하고, GitHub Actions로 10개 서버에 동시 배포합니다.


결론부터 말하면 현재 이 시스템은 한국어(ko), 영어(en), 독일어(de), 일본어(ja), 프랑스어(fr), 스페인어(es), 포르투갈어(pt), 네덜란드어(nl), 이탈리아어(it), 터키어(tr) 10개 언어로 매일 블로그를 자동 발행하고 있습니다.

지금부터 이 시스템을 처음부터 끝까지 낱낱이 공개하겠습니다. 아키텍처 설계부터 골치 아팠던 버그들, SEO 최적화 과정까지 전부요.


ARCHITECTURE

2. 전체 아키텍처

10개 서버 다국어 블로그 자동화 아키텍처 — Python, WordPress, Cloudflare R2


전체 구조를 한 문장으로 요약하면: Vultr 10대 VPS에서 각각 Python 스케줄러가 2시간마다 실행되며, AI로 콘텐츠를 생성하고 WordPress REST API로 자동 발행합니다.

인프라 구성

서버 — Vultr VPS 10대 (언어별 개별 서버, 각 $6/월)

DNS/CDN — Cloudflare (각 언어 도메인에 적용)

CMS — WordPress + LiteSpeed Cache + Rank Math SEO

이미지 스토리지 — Cloudflare R2 (커스텀 도메인 CDN)

AI 모델 — Claude Sonnet (콘텐츠 생성), GPT-4o (보조), GPT-image-1 (이미지)

CI/CD — GitHub Actions (main 브랜치 push → 10개 서버 동시 자동 배포)


코드 구조

config/languages/{lang}/ — 언어별 설정 파일 (블로그 정보, 카테고리, 스타일, 프롬프트)

src/generator/ — AI 콘텐츠 생성 파이프라인 (주제→포스트→썸네일)

src/scheduler/ — FIFO 큐 기반 자동 발행 스케줄러

src/wordpress/ — WordPress REST API 클라이언트

src/report/ — GA4 + GSC 기반 운영 리포트 시스템

scripts/ — 서버 동기화, SEO 마이그레이션, Indexing API 스크립트


특히 단일 소스 원칙을 철저히 지켰습니다. 한 번 코드를 변경하면 GitHub Actions가 10개 서버에 자동으로 배포합니다. 각 서버는 같은 코드를 실행하지만, LANGUAGE=ko (또는 en, de, ja...) 환경변수 하나로 언어가 결정됩니다.

배포 자동화 워크플로우

git push → GitHub Actions 트리거 → matrix strategy로 10개 서버 병렬 SSH 배포 → 각 서버에서 pip install + systemctl reload. 전체 배포 시간 약 2분.


AI PIPELINE

3. AI 콘텐츠 생성 파이프라인

콘텐츠 생성은 크게 3단계로 이루어집니다. 주제 선정 → 포스트 본문 생성 → 썸네일 생성. 각 단계를 살펴보겠습니다.

3-1. 주제 선정

주제는 카테고리 분류 체계를 기반으로 AI가 자동 선정합니다. 개발 / IT·테크 / 자기계발 / 생활정보 / 게임 / 애니 등 대분류에 소분류가 있고, 중복 발행을 방지하기 위해 topic_history.json에 발행 이력을 저장합니다.

문제

AI가 같은 주제를 중복으로 제안하는 문제

Claude에게 "새로운 주제를 제안해줘"라고 하면 이미 발행한 주제와 유사한 것을 추천하는 경우가 많았습니다. 특히 인기 있는 주제(AI 도구, 개발 생산성 등)는 반복 추천 빈도가 높았습니다.

해결 — 발행 이력을 프롬프트에 주입

# topic_history.json에서 최근 50개 주제 추출
recent_topics = history.get_recent(50)

# 프롬프트에 이력 주입
prompt = f"""
다음은 이미 발행된 주제입니다. 절대 중복되지 않게 새 주제를 제안하세요:
{recent_topics}
"""

3-2. 포스트 본문 생성

본문은 Claude Sonnet이 생성합니다. 단순히 "글 써줘"가 아니라, 언어별로 세밀하게 조정된 시스템 프롬프트가 있습니다.

언어팩 구조 (config/languages/{lang}/)

blog.json — 블로그 이름, 도메인, 언어 코드, 로케일

categories.json — 해당 언어권에 최적화된 카테고리 목록

styles.json — 색상 팔레트 (언어별로 브랜드 컬러가 다름)

prompts.py — 해당 언어로 작성된 시스템 프롬프트

examples/ — 언어별 포스트 HTML 예시 파일


핵심 포인트

독일어 블로그는 독일어 프롬프트로 독일어 독자를 위한 콘텐츠를 생성합니다. 단순 번역이 아니라, 해당 언어권의 문화·법률·생활환경에 맞게 현지화된 글이 생성됩니다. 예를 들어 스페인어 블로그의 부동산 포스트는 스페인 임대차법을 기준으로 작성됩니다.


HTML 템플릿은 5종으로 다변화되어 있습니다. 카드형, 매거진형, 미니멀형, 클래식형 등. 매번 같은 레이아웃이면 중복 콘텐츠로 인식될 수 있기 때문에 다양성을 확보했습니다.

또한 사전조사 기반 생성 기능도 있습니다. claude-web/ 폴더에 마크다운 파일을 넣으면, 해당 조사 내용을 바탕으로 더 깊이 있는 포스트가 생성됩니다.


THUMBNAIL

4. 썸네일 자동 생성

썸네일은 Pillow(Python 이미지 라이브러리)로 생성합니다. AI가 생성한 배경 이미지 위에 제목 텍스트를 오버레이하는 방식입니다.

썸네일 생성 파이프라인

1단계 — GPT-image-1로 포스트 주제에 맞는 배경 이미지 생성 (1280×720)

2단계 — Pillow로 배경 이미지 위에 제목 텍스트 오버레이

3단계 — WebP 변환 (파일 크기 최적화)

4단계 — Cloudflare R2에 업로드 후 CDN URL 획득


폰트 문제와 해결

썸네일 개발 과정에서 폰트 이슈가 많았습니다.

버그 01

macOS에서 한국어 폰트 깨짐

Hiragino 폰트로 한국어를 렌더링하면 글자가 깨지는 현상. 로컬 개발 환경(macOS)과 서버(Linux) 환경의 폰트가 달라 생기는 문제였습니다.

해결 — OS 감지 후 폰트 자동 선택

import platform

if platform.system() == "Darwin":
    # macOS: Apple SD Gothic Neo
    font_path = "/System/Library/Fonts/AppleSDGothicNeo.ttc"
else:
    # Linux (서버): Noto Sans CJK
    font_path = "/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc"

버그 02

다국어 썸네일 폰트 선택 문제

10개 언어가 각각 다른 폰트를 필요로 합니다. CJK(한국어, 일본어)는 Noto Sans CJK, 라틴 계열(영어, 독일어 등)은 Montserrat나 Noto Sans를 사용해야 합니다.

해결 — 언어 코드 기반 폰트 자동 선택

CJK_LANGS = {"ko", "ja", "zh"}

def get_font_path(language: str) -> str:
    if language in CJK_LANGS:
        return NOTO_SANS_CJK_PATH
    else:
        return NOTO_SANS_LATIN_PATH

버그 03

썸네일 이모지 ☒ 렌더링 버그

AI가 생성한 포스트 제목에 이모지가 포함될 경우 Pillow가 렌더링하지 못해 □(빈 박스)가 표시되는 문제. Noto Color Emoji 폰트가 없는 서버에서 특히 심각했습니다.

해결 — 썸네일 생성 전 이모지 제거

import re

def strip_emoji(text: str) -> str:
    emoji_pattern = re.compile(
        "[\U00010000-\U0010FFFF]",
        flags=re.UNICODE
    )
    return emoji_pattern.sub("", text).strip()

IMAGE HOSTING

5. Cloudflare R2 이미지 호스팅 마이그레이션

초기에는 이미지를 GitHub 레포에 저장했습니다. 포스트당 5~7개 이미지, 10개 블로그에서 매일 발행하면 금방 레포 용량이 폭발합니다. 게다가 GitHub은 이미지 CDN으로 적합하지 않습니다. 결국 Cloudflare R2로 전면 마이그레이션을 결정했습니다.

R2 선택 이유

무료 이그레스 — Cloudflare CDN을 통한 트래픽은 무료 (AWS S3는 GB당 과금)

커스텀 도메인 — images.kwonputer.com 등 도메인 연결 가능

S3 호환 API — boto3로 그대로 사용 가능 (코드 변경 최소)

글로벌 CDN — 10개 언어 사용자 모두에게 빠른 이미지 로딩


마이그레이션의 핵심은 발행 후 로컬 이미지 자동 정리입니다. 포스트를 WordPress에 발행하면 이미지가 R2에 업로드되고, 로컬의 임시 이미지 파일은 자동으로 삭제됩니다. 서버 용량을 거의 차지하지 않습니다.

이미지 처리 흐름

AI 이미지 생성 → WebP 변환 → R2 업로드 → CDN URL 획득 → HTML에 삽입 → 로컬 파일 삭제. 이미지 병렬 처리로 생성 시간도 크게 단축했습니다.


SCHEDULER

6. 자동 발행 스케줄러

스케줄러는 이 시스템의 심장입니다. 매일 정해진 수의 포스트를 랜덤한 시간에 자동 발행합니다. 사람이 발행하는 것처럼 자연스러운 패턴을 만들기 위해서입니다.

스케줄러 핵심 설계

FIFO 큐 — 생성된 포스트는 큐에 순서대로 등록됨

랜덤 발행 시간 — 하루 발행 시간대(예: 07:00~22:00)에서 랜덤 시간 배정, 최소 3시간 간격

cron 2시간 주기 — 서버 cron이 2시간마다 스케줄러 실행 → 발행 예정 시간 도래 시 WP에 발행

자동 재시도 — 발행 실패 시 자동 재시도, 3회 실패 시 영구 실패로 표시

헬스체크 + Slack 알림 — 큐 상태·발행 실패·콘텐츠 부족 시 Slack 알림


스케줄러 상태 확인 예시

$ python -m src scheduler status

전체 큐: 43개 | 대기: 9개 | 발행 완료: 34개
하루 발행 수: 3개 | 발행 시간대: 07:00 ~ 22:00
다음 발행: 2026-03-24T08:57 (EN - Local Restaurant Guide)
예상 소진: 3.0일 (9개 / 하루 3개)

중복 발행 방지 — 3중 방어 체계

실제 운영 중 가장 골치 아팠던 문제가 중복 발행이었습니다. 같은 포스트가 두 번 올라가는 것은 SEO에 매우 치명적입니다.

3중 방어 체계

1차 방어 — 로컬 메타데이터에서 이미 발행된 포스트 필터링

2차 방어 — WordPress REST API로 slug 중복 확인 (draft/trash 포스트 포함)

3차 방어 — 발행 전 제목 해시값 비교로 최종 중복 차단


트러블슈팅 포인트

초기에 draft 상태의 포스트는 중복 체크에서 제외했더니 같은 글이 draft + published로 두 번 올라가는 문제가 발생. draft와 trash 포스트도 중복 체크 대상에 포함하는 것으로 해결했습니다.


CI/CD

7. GitHub Actions로 10개 서버 동시 배포

코드를 수정할 때마다 10개 서버에 SSH로 하나씩 접속해서 배포하면... 생각만 해도 끔찍합니다. GitHub Actions의 matrix strategy로 이 문제를 완전히 해결했습니다.

GitHub Actions matrix 전략

strategy:
  matrix:
    server:
      - { lang: ko, host: "server-ko.example.com" }
      - { lang: en, host: "server-en.example.com" }
      - { lang: de, host: "server-de.example.com" }
      # ... 10개 서버

steps:
  - name: Deploy to ${{ matrix.server.lang }}
    run: |
      rsync -avz --exclude='.env' \
        src/ config/ requirements.txt \
        root@${{ matrix.server.host }}:/opt/tistory-blog-auto/

배포 제외 항목

각 서버의 data/posts_metadata.json, data/publish_schedule.json, posts/ 폴더는 배포 제외입니다. 서버별로 독립적인 데이터이기 때문입니다. 코드만 배포하고 데이터는 각 서버가 자체 관리합니다.


SEO AUTOMATION

8. SEO 자동화 — Rank Math + 구조화 데이터

SEO는 블로그 수익화의 핵심입니다. 자동으로 생성되는 포스트라도 SEO 점수가 높아야 합니다. 다음은 자동화된 SEO 항목들입니다.

자동 처리되는 SEO 항목

포커스 키워드 — AI가 포스트 주제에서 추출, Rank Math에 자동 설정

SEO 메타 설명 — 120~160자 범위로 AI 생성, 발행 전 길이 검증

SEO 슬러그 — 영문 키워드 기반 URL-friendly 슬러그 자동 생성

JSON-LD 구조화 데이터 — Article, FAQ, BreadcrumbList 스키마 자동 삽입

이미지 alt 텍스트 — 각 이미지에 맥락에 맞는 alt 텍스트 자동 생성

이미지 width/height — CLS 방지를 위한 크기 속성 자동 삽입

내부 링크 — FAQ 섹션 하단에 관련 포스트 자동 연결


FAQ 리치 스니펫 자동 삽입

Google 검색 결과에서 "사람들이 자주 묻는 질문" 섹션으로 노출되는 FAQ 리치 스니펫을 모든 포스트에 자동으로 삽입합니다.

FAQ 스키마 구조

{
  "@context": "https://schema.org",
  "@type": "FAQPage",
  "mainEntity": [
    {
      "@type": "Question",
      "name": "포스트 주제 관련 질문 1",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "AI가 생성한 답변"
      }
    }
  ]
}

Rank Math 사이트맵 캐시 버그

운영 중 발견한 중요한 버그였습니다. WordPress REST API로 포스트를 발행하면 Rank Math 사이트맵 캐시가 갱신되지 않아, 새 포스트가 사이트맵에 포함되지 않는 문제였습니다.

버그 04

REST API 발행 시 Rank Math 사이트맵 미갱신

Rank Math는 WordPress 관리자에서 포스트를 발행할 때 사이트맵을 갱신합니다. 하지만 REST API로 발행하면 이 훅이 트리거되지 않아 사이트맵이 오래된 캐시를 유지합니다. 새 포스트가 Google에 색인되지 않는 치명적인 결과로 이어질 수 있습니다.

해결 — mu-plugin으로 REST API 발행 시 캐시 자동 삭제

// mu-plugins/flush-sitemap-cache.php
add_action('rest_after_insert_post', function($post) {
    if ($post->post_status === 'publish') {
        do_action('rank_math/sitemap/clear_cache');
    }
});

BUG FIXES

9. 발견하고 수정한 버그들

시스템을 운영하면서 만난 주요 버그들을 정리합니다. 비슷한 시스템을 구축하는 분들에게 도움이 될 것 같습니다.

버그 05

LANGUAGE 환경변수 로딩 버그

서버에서 LANGUAGE=en으로 설정했는데 항상 ko로 동작하는 문제. settings.py에서 load_dotenv()를 호출하기 전에 os.getenv()를 먼저 읽어버려 .env 파일이 로드되지 않은 상태였습니다.

해결 — 모듈 최상단에서 load_dotenv() 먼저 호출

settings.py 최상단에 from dotenv import load_dotenv; load_dotenv() 추가로 해결.


버그 06

WP 카테고리 HTML 엔티티 디코딩 미처리

WordPress REST API에서 카테고리명을 가져오면 &가 &로 표시되는 HTML 엔티티 인코딩 문제. 카테고리 매핑이 실패해 포스트가 잘못된 카테고리에 등록됐습니다.

해결 — html.unescape() 적용

import html
category_name = html.unescape(raw_name)
# "IT & 개발" → "IT & 개발"

버그 07

AI IMAGE 플레이스홀더 누락 시 이미지 미삽입

Claude가 HTML을 생성할 때 [AI IMAGE] 플레이스홀더를 빠뜨리는 경우가 있었습니다. 이 경우 이미지 삽입 로직이 동작하지 않아 이미지가 없는 포스트가 발행됐습니다.

해결 — h2 태그 기반 자동 플레이스홀더 삽입

플레이스홀더가 없으면 첫 번째 <h2> 태그 바로 아래에 자동으로 플레이스홀더를 삽입하는 fallback 로직 추가.


버그 08

리포트 HTML <hr> 티스토리 호환성 문제

운영 리포트를 티스토리에 올릴 때 섹션 간격으로 사용한 <hr> 태그가 티스토리 에디터에서 수평선으로 렌더링되는 문제. 레이아웃이 완전히 망가졌습니다.

해결 — <hr> → 투명 <div> 교체

<!-- Before -->
<hr style="height: 60px;">

<!-- After -->
<div style="padding-top: 60px;"></div>

10개 다국어 블로그 SEO 전수검사 — Google Search Console 노출/클릭 분석


SEO AUDIT

15. 10개 블로그 SEO 전수검사 — 4단계 개선

블로그를 만든 지 약 30일 후, 전체 SEO 상태를 전수검사했습니다. Google Search Console 데이터를 보면서 깜짝 놀랐습니다.

검색 성과 (2026년 3월, 30일간)

블로그 노출 클릭 CTR 평균순위
Kwonglish (EN) 309 0 0.0% 8.7
Kwonnen (DE) 123 1 0.8% 16.0
Kwontudo (PT) 98 0 0.0% 7.4
Kwonsejo (ES) 61 2 3.3% 8.7
Kwonputer (KO) 14 2 14.3% 17.6

10개 블로그 합산: 노출 798회, 클릭 5회 (30일간)


EN 블로그가 309번이나 노출됐는데 클릭이 0이라는 게 충격이었습니다. 이건 단순히 콘텐츠 품질 문제가 아니라 온페이지 SEO 세팅 문제였습니다. 전수검사를 통해 다음을 발견했습니다.

P0 치명적 문제 (즉시 수정)

9개 블로그 홈페이지 제목 깨짐 — tagline이 없어 "Kwonglish -" 처럼 끝남

9개 블로그 홈페이지 메타 설명 없음 — Google이 자체 스니펫 생성 → CTR 저하

9개 블로그 OG 태그 불완전 — SNS 공유 시 미리보기 깨짐


4단계 개선 실행 결과

Phase 1 — 긴급 수정

☑ 9개 블로그 tagline WP REST API로 자동 설정

☑ 9개 블로그 Rank Math 홈페이지 메타 설명 일괄 설정

☑ 9개 블로그 OG/Twitter Card 이미지 미디어 라이브러리 등록 + 설정


Phase 2 — E-E-A-T 강화

☑ 9개 블로그 About 페이지 AI 생성 + WP 발행 (각 언어별 현지화)

☑ 9개 블로그 Contact 페이지 AI 생성 + WP 발행


Phase 3 — 기술적 SEO

☑ 이미지 width/height/lazy-loading 자동 삽입 (CLS 개선)

☑ 이미지 파일명 키워드 기반 슬러그로 변경 (이미지 검색 노출)

☑ Organization JSON-LD + Breadcrumb 스키마 전체 활성화

☑ LiteSpeed CSS 최소화 이미 활성화 확인


Phase 4 — 발행 파이프라인 검증

☑ 발행 전 SEO 자동 검증 로직 추가 (메타 설명 길이, 키워드 배치)

☑ 포스트 발행 수 3개/일로 증가 (콘텐츠 축적 가속)


전수검사 최종 결과

홈페이지 타이틀, 메타 설명, OG/Twitter Card, Canonical URL, hreflang, JSON-LD, About/Contact 페이지 등 140/140 항목 전부 PASS. 사이트맵 총 463개 URL 포함.


INDEXING

16. Google Indexing API로 색인 가속화

SEO 최적화를 끝낸 후, Google이 새로 개선된 메타데이터를 다시 크롤링하기를 기다리는 건 비효율적입니다. Google Indexing API를 사용하면 URL을 직접 제출해 색인을 촉진할 수 있습니다.

색인 요청 자동화 스크립트

서버 자동 수집 — 10개 서버에 SSH로 접속해 WordPress REST API로 발행된 포스트 URL 수집

일괄 제출 — Google Indexing API로 URL_UPDATED 타입으로 제출

쿼타 관리 — 하루 200개 쿼타 초과 시 나머지 URL을 파일로 저장, 다음 실행 시 이어서 처리

결과 — 10개 블로그 전체 388개 URL 색인 요청 완료


색인 요청 스크립트 사용법

# 전체 블로그 URL 수집 + 일괄 제출
python scripts/request_indexing.py

# 쿼타 초과로 남은 URL만 이어서 제출
python scripts/request_indexing.py --remaining

# 특정 URL 파일 지정
python scripts/request_indexing.py --file /tmp/urls.txt

Google Sandbox 효과

신규 도메인은 일반적으로 3~6개월간 Google이 검색 순위를 억제합니다(Sandbox 효과). 현재 블로그 개설 1~2개월차이므로 낮은 노출 자체는 예상 범위입니다. SEO 최적화 + 색인 가속화 + 콘텐츠 축적을 병행하면 Sandbox 종료 시점(약 3개월)에 급격한 노출 증가를 기대할 수 있습니다.


RESULTS & FUTURE

17. 현재 성과와 앞으로의 계획

현재까지 만든 것들

☑ 10개 언어 WordPress 블로그 운영 중

☑ AI 콘텐츠 생성 → 썸네일 → Cloudflare R2 → WP 발행 완전 자동화

☑ GitHub Actions 10개 서버 병렬 배포 파이프라인

☑ FIFO 큐 기반 랜덤 시간 자동 발행 스케줄러 (3개/일/블로그)

☑ 운영 리포트 시스템 (GA4 + GSC → HTML 리포트)

☑ 10개 블로그 SEO 전수검사 140/140 PASS

☑ Google Indexing API 388개 URL 색인 요청

☑ Slack 헬스체크 알림 시스템


앞으로의 계획

단기 (1개월)

콘텐츠 확충 — 현재 35~70개 포스트/블로그를 100개 이상으로

CTR 최적화 — GSC 데이터로 노출 대비 클릭 0인 포스트 제목/메타 개선

Google Analytics 전환 추적 — 실제 수익 연결 지표 설정


중기 (3개월)

Google Sandbox 탈출 — 3개월 지점에서 노출 급증 기대

Google AdSense 심사 신청 — 충분한 콘텐츠 확보 후

내부 링크 고도화 — 관련 포스트 간 크로스링크 자동화


이 프로젝트에서 배운 것

자동화는 완벽한 시스템이 아니라 빠르게 반복할 수 있는 시스템을 목표로 해야 합니다. 처음부터 완벽할 수 없고, 운영하면서 버그를 발견하고 개선하는 사이클이 중요합니다.

AI 콘텐츠도 SEO 기반이 제대로 갖춰져 있지 않으면 아무리 좋은 글도 검색에 노출되지 않습니다. 기술적 SEO는 콘텐츠보다 먼저 완성되어야 합니다.


BRAND IDENTITY

10. KWON 브랜드 로고 시스템

KWON 10개 다국어 블로그 브랜드 로고 시스템 — Pillow 자동 생성


10개 블로그를 운영하다 보니 각 블로그의 정체성이 필요했습니다. 디자이너에게 맡기면 비용이 발생하고, AI 이미지 생성도 일관성이 떨어집니다. 그래서 Python Pillow로 직접 로고 생성 시스템을 구축했습니다.

브랜드 컨셉 — 텍스트에 의미를 담다

모든 블로그 도메인이 kwon + 언어 의미 단어 조합입니다.

Kwonputer (ko) — Kwon + Computer

Kwonglish (en) — Kwon + English

Kwonnen (de) — Kwon + Können (독일어: 능력)

Kwonteki (ja) — Kwon + テキ (일본어: 적합한)

Kwontenu (fr) — Kwon + Contenu (프랑스어: 콘텐츠)

Kwonsejo (es) — Kwon + Consejo (스페인어: 조언)

Kwontudo (pt) — Kwon + Tudo (포르투갈어: 모든 것)

Kwonnis (nl) — Kwon + Kennis (네덜란드어: 지식)

Kwontento (it) — Kwon + Contento (이탈리아어: 만족)

Kwontrol (tr) — Kwon + Kontrol (터키어: 통제)


로고 생성 자동화 (generate_logos.py)

워드마크 PNG — 10개 블로그 × 투명/흰색 배경 (Montserrat Black 폰트)

원형 기어 아이콘 — 10개 블로그 × 5가지 사이즈 (16/32/64/128/256px)

사이트 대표 아이콘 — 1024×1024 고해상도 (파비콘/SNS 공유용)

폰트는 Montserrat TTF(Black, Medium)를 fonts/ 폴더에 번들링해서 서버 환경에 무관하게 동일한 결과물을 보장합니다.


로고 시스템의 실용적 효과

브랜드 로고가 생기면서 OG 이미지, 파비콘, 썸네일 워터마크에 일관된 시각적 정체성을 적용할 수 있게 됐습니다. SEO 전수검사 시 og:image 항목에 이 로고 이미지를 사용해 10개 블로그 모두 PASS 처리했습니다.


EXPERIMENT & PIVOT

11. AI 소설 자동 발행 시스템 — 구현에서 폐기까지

솔직하게 말하면 이 섹션이 이 프로젝트에서 가장 많이 배운 부분입니다. 잘 만든 기능을 과감하게 버리는 결정에 관한 이야기입니다.

구현 — 에피소드 연재 시스템

AI가 장편 소설을 에피소드 단위로 자동 생성하고, 매일 새 화를 발행하는 시스템을 만들었습니다. 웹소설 플랫폼처럼 "다음 화" 네비게이션 버튼도 달렸고, 이전 화 발행 시 "다음 화 준비 중" 표시도 자동으로 업데이트됐습니다.

구현된 기능

에피소드 이전/다음 네비게이션 버튼 — 자동 삽입

에피소드 중복 발행 방지 — 화수 기반 dedup 로직

이전 화 자동 업데이트 — 새 화 발행 시 이전 화의 "준비 중" 표시 → 링크로 교체

episodes_per_day 설정 — 스케줄러와 통합, 하루 N화 자동 발행


폐기 — 왜 없앴나

폐기 이유

콘텐츠 방향성 불일치 — 기술 블로그와 소설 콘텐츠는 독자층이 완전히 다릅니다. SEO 관점에서 키워드 일관성을 해치고 도메인 토픽 집중도가 떨어집니다.

AI 소설의 품질 한계 — Claude가 생성하는 소설은 일관된 스토리라인 유지가 어렵습니다. 에피소드가 쌓일수록 앞 내용과의 연속성이 무너졌습니다.

수익화 경로 불명확 — 소설 트래픽은 AdSense 단가가 낮고, 주력 기술 콘텐츠 대비 ROI가 떨어졌습니다.


결국 소설 시스템 전체를 코드베이스에서 완전히 제거했습니다. 관련 커밋이 feat(구현) → fix(버그 수정 3개) → chore(전체 삭제)로 이어집니다. 코드를 지운 건 아쉽지만, 명확한 이유가 있는 결정이었습니다.

교훈

기능을 완성도 있게 구현했더라도, 전체 전략과 맞지 않으면 과감하게 제거해야 합니다. 코드베이스가 단순해지면 유지보수가 쉬워지고, 핵심 기능에 집중할 수 있게 됩니다.


ANALYTICS

12. 운영 리포트 시스템 — GA4 + GSC → HTML 자동 생성

10개 블로그의 상태를 수동으로 하나씩 확인하는 건 불가능합니다. GA4(Google Analytics 4)와 GSC(Google Search Console) 데이터를 자동으로 수집해서 HTML 리포트로 만드는 시스템을 구축했습니다.

리포트 시스템 구성

GA4 연동 — Google Analytics Data API v1으로 방문자 수, 세션, 이탈률 수집

GSC 연동 — Search Console API로 노출수, 클릭수, CTR, 평균 순위 수집

스크린샷 자동화 — Playwright로 각 블로그 홈페이지 + 상위 포스트 스크린샷 캡처

AI 내러티브 — 수집된 데이터를 Claude가 분석해 한국어 인사이트 텍스트 생성

HTML 리포트 출력 — 티스토리에 바로 올릴 수 있는 포맷으로 생성


리포트 CLI 사용법

# 전체 기간 리포트 생성
python -m src report generate

# 최근 7일 리포트
python -m src report generate --period 7

# 스크린샷 없이 빠르게 생성
python -m src report generate --skip-screenshots

# AI 내러티브 없이 (수치 데이터만)
python -m src report generate --skip-ai

리포트를 만든 덕분에 10개 블로그 SEO 전수검사도 가능했습니다. GSC 데이터에서 "309 노출 / 0 클릭"이라는 이상 징후를 발견한 것도 이 리포트 시스템 덕분입니다.

버그

리포트 썸네일 생성 시 AI IMAGE 플레이스홀더 충돌

리포트 HTML을 생성할 때 일반 포스트용 이미지 삽입 로직이 실행되어 리포트 내 스크린샷 자리에 엉뚱한 AI 이미지가 들어가는 문제가 있었습니다. 리포트 생성 파이프라인을 일반 포스트 파이프라인과 완전히 분리해서 해결했습니다.


LEGAL & MIGRATION

13. 법적 페이지 + 마이그레이션 도구 6종

법적 페이지 자동 생성 CLI

AdSense 심사, GDPR, 각국 개인정보보호법 준수를 위해 10개 블로그 모두에 법적 페이지가 필요합니다. 10개 언어로 각각 작성하면 작업량이 방대합니다. CLI 명령 하나로 자동 생성하도록 구현했습니다.

법적 페이지 CLI

# 개인정보처리방침 + 면책조항 + 쿠키정책 WP 발행
python -m src wp legal-pages

# 발행 전 HTML 미리보기
python -m src wp legal-pages --dry-run

각 페이지는 해당 언어권의 법률 환경에 맞게 현지화됩니다. 독일어 블로그는 DSGVO(독일 GDPR), 브라질 포르투갈어 블로그는 LGPD 기준으로 작성됩니다.

마이그레이션 도구 6종

이미 발행된 수백 개의 포스트를 일괄 개선해야 할 때 사용하는 도구들입니다. 처음부터 완벽하게 만들 수 없기 때문에, 나중에 일괄 업그레이드할 수 있는 마이그레이션 도구를 함께 구축했습니다.

마이그레이션 도구 목록

headings — <p>로 작성된 제목을 <h2>/<h3>로 일괄 변환

alt-text — 영문 alt 텍스트를 한국어/해당 언어로 일괄 변환

json-ld — 기존 포스트에 JSON-LD 구조화 데이터 일괄 삽입

seo — 헤딩 + alt + JSON-LD + SEO 설명 통합 일괄 처리

wp-seo — WordPress slug + Rank Math 메타데이터 일괄 마이그레이션

thumbnails — 기존 포스트 썸네일 AI 재생성 + WP featured image 교체


안전한 마이그레이션 — dry-run 지원

# 실제 변경 전 미리보기
python -m src migrate all --dry-run

# 썸네일만 강제 재생성 (기존 이미지 덮어씀)
python -m src migrate thumbnails --force

# 특정 포스트만 처리
python -m src migrate thumbnails --post-id abc123

SERVER OPS

14. 서버 운영 도구 — sync.sh + LiteSpeed 자동화

GitHub Actions로 코드 배포는 자동화했지만, 포스트 파일과 메타데이터는 서버별로 다르기 때문에 수동으로 관리해야 합니다. 이를 위한 운영 전용 쉘 스크립트를 만들었습니다.

scripts/sync.sh 명령 목록

posts — 로컬에서 생성한 포스트 HTML 파일을 서버로 전송

metadata-push — 로컬 메타데이터 JSON → 서버로 동기화

metadata-pull — 서버 메타데이터 → 로컬로 가져오기

full — 포스트 전송 + draft→ready 승격 + 큐 등록 + 메타데이터 pull 한번에

promote — 서버의 draft 포스트를 ready 상태로 일괄 승격

queue — 승격된 포스트를 스케줄러 발행 큐에 등록

status — 10개 서버 상태 한눈에 확인 (큐 크기, 다음 발행 시간 등)

migrate-seo — 모든 서버에 SEO 마이그레이션 일괄 실행

migrate-thumbnails — 모든 서버의 썸네일 AI 재생성 + WP featured image 교체


LiteSpeed Cache 일괄 설치 자동화

10개 서버에 WordPress를 세팅하고 LiteSpeed Cache 플러그인을 수동으로 설치하는 건 반복 작업입니다. WP-CLI를 활용한 일괄 설치 스크립트로 자동화했습니다.

LiteSpeed + 필수 플러그인 일괄 설치

# WP-CLI로 플러그인 일괄 설치 (SSH 접속 후)
wp plugin install litespeed-cache --activate
wp plugin install seo-by-rank-math --activate
wp plugin install wordfence --activate

# LiteSpeed Cache 최적화 설정 적용
wp litespeed-option set cache-browser 1
wp litespeed-option set optm-css_min 1
wp litespeed-option set optm-js_min 1

wp_category_map.json 배포 제외 이슈

각 서버는 WordPress 카테고리 ID가 다릅니다. 처음에 wp_category_map.json을 코드베이스에 포함시켰다가 서버마다 카테고리 ID가 달라 포스트가 잘못된 카테고리에 등록되는 문제가 발생했습니다. 해당 파일을 deploy.yml 배포 제외 목록에 추가하고, 각 서버에서 wp sync-categories로 독립적으로 생성하도록 변경했습니다.


긴 글을 읽어주셔서 감사합니다!

AI로 10개 언어 블로그를 자동화하는 여정을 처음부터 끝까지 공개했습니다. 아직 수익화까지는 갈 길이 멀지만, 인프라는 탄탄하게 구축됐습니다.

비슷한 프로젝트를 진행 중이거나 궁금한 점이 있으시면 댓글로 남겨주세요. 가능한 모든 질문에 답변 드리겠습니다.

이 블로그도 동일 시스템으로 운영되고 있습니다 🤖

반응형
저작자표시 비영리 변경금지 (새창열림)

'IT · 테크 > 마케팅 · 수익화' 카테고리의 다른 글

10개 다국어 블로그 운영 D+59 리포트 — 방문자 1,091명, 검색노출 1,025회 달성  (0) 2026.04.01
GA4 퍼널 분석으로 마케팅 전환율 0%의 원인을 찾은 이야기  (0) 2026.03.22
메타(인스타그램) 광고 처음 세팅하기 - 하루 1,500원으로 3개국 광고 시작한 과정  (0) 2026.03.18
'IT · 테크/마케팅 · 수익화' 카테고리의 다른 글
  • 10개 다국어 블로그 운영 D+59 리포트 — 방문자 1,091명, 검색노출 1,025회 달성
  • GA4 퍼널 분석으로 마케팅 전환율 0%의 원인을 찾은 이야기
  • 메타(인스타그램) 광고 처음 세팅하기 - 하루 1,500원으로 3개국 광고 시작한 과정
권퓨터
권퓨터
만드는 걸 좋아하는 개발자의 기록. 코드든 글이든, 일단 만들어 봅니다.
  • 권퓨터
    권퓨터: Kwonputer
    권퓨터
  • 티스토리 홈 관리자
  • 전체
    오늘
    어제
    • 분류 전체보기 (557)
      • 개발 (56)
        • 프로젝트 (5)
        • 모바일 (44)
        • 프론트엔드 (0)
        • 백엔드 (2)
        • 인프라 (0)
        • AI · 머신러닝 (4)
      • IT · 테크 (8)
        • 기술 트렌드 (3)
        • 도구 · 생산성 (1)
        • 제품 리뷰 · 추천 (0)
        • 마케팅 · 수익화 (4)
      • 자기계발 (7)
        • 공부법 · 언어 (0)
        • 취업 · 커리어 (7)
      • 아카이브 (486)
        • 일기 (480)
        • 취미 (6)
  • 블로그 메뉴

    • 홈
  • 링크

    • 블로그 이전
  • 공지사항

    • 서브 블로그 => https://kwonputer.com/
  • 인기 글

  • 태그

    flutter 개발자
    파이썬
    서버리스 아키텍처
    파이썬 기초
    클린 아키텍처
    AWS CDK
    kotlin
    injectable
    사이드프로젝트
    크로스플랫폼
    OpenAI GPT
    ai 게임 개발
    Clean Architecture
    aws lambda
    FACEBOOK광고
    1인개발
    dynamodb
    flutter
    python 기초
    https://github.com/kwongeneral/kortfolio.git
    TypeScript
    python
    다국어 블로그
    Prompt Engineering
    상태관리
    https://www.kwonputer.shop/
    flutter 면접 질문
    내러티브 게임
    Single Table Design
    riverpod
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.6
권퓨터
AI로 10개국어 블로그를 혼자 운영하는 방법 — 자동화 시스템 구축 전체 공개
상단으로

티스토리툴바