애드센스 재심사 전 34편 전수 점검 — 코드 뜯어보니 나온 허점 3가지

📚 이 글은 “개발자가 AI 자동화로 부업하는 실전 기록” 시리즈입니다.

34편: 애드센스 탈락 이후 파이프라인 코드로 품질을 강제하다

ep34에서 publish_draft.py에 태그 검증 로직을 넣고, 글쓰기 기준도 문서화했다. 끝낸 순간 뿌듯했는데, 하루쯤 지나서 불편한 생각이 들었다.

코드를 고쳐봤자 이미 발행된 34편은 그 코드를 한 번도 거치지 않았다.

파이프라인에 품질 게이트를 달았다고 해서 기존 글들이 소급 적용되는 건 아니다. 애드센스 재심사는 사이트 전체를 보는데, 새 글만 잘 쓰면 뭐가 달라지겠나 싶었다. 그래서 published.json에 기록된 34편을 처음부터 다시 훑었다. 결과적으로 코드 안에서만 찾아봐도 허점이 세 군데나 나왔다.


점검에 앞서 — 기준을 먼저 정했다

무작정 글을 다시 읽는 건 비효율적이다. 애드센스 ‘가치 없는 콘텐츠’ 판정 기준이 뭔지는 정확히 공개돼 있지 않지만, 내가 ep33에서 받은 피드백과 구글 정책 설명을 종합하면 세 가지가 핵심이었다.

  • ✅ 메타데이터가 제대로 채워져 있는가 (태그, excerpt, SEO 필드)
  • ✅ 본문이 충분히 길고 구체적인가 (얇은 콘텐츠 아닌가)
  • ✅ 콘텐츠가 독자에게 실질적인 가치를 주는가 (일반론 나열인가, 실제 경험인가)

세 번째는 글 하나하나를 직접 읽어야 알 수 있는 영역이라 시간이 걸린다. 그런데 첫 번째와 두 번째는 코드와 데이터만 봐도 판단할 수 있다. 거기서 시작했다.

전수 점검의 출발점은 “코드가 무엇을 보장하고, 무엇을 보장하지 않는가”를 확인하는 것이었다.


허점 1 — 태그가 없는 글이 절반 이상이다

publish.py를 열어보면 TAG_ID_MAP이 있다. WordPress 태그 13종과 그 ID를 매핑한 딕셔너리다.

⚙️ 코드 위치: src/publish.py — TAG_ID_MAP 정의부

TAG_ID_MAP = {
    "블로그 자동화": 15,
    "Claude API": 16,
    "AI 부업": 17,
    "WordPress": 18,
    "블로그 수익화": 19,
    "애드센스": 20,
    "SEO": 21,
    "API 연동": 22,
    "트래픽 성장": 23,
    "Python": 24,
    "Next.js": 25,
    "디버깅": 26,
    "레거시 마이그레이션": 27,
}

이 태그 체계는 ep34 작업 때 정비됐다. 그 이전에는 태그를 체계적으로 관리하지 않았다. published.json을 보면 ep24부터 date 필드가 붙기 시작하는데, 이게 파이프라인이 본격적으로 정비된 시점이다. ep1부터 ep23까지는 date 필드조차 없다.

즉, 전체 34편 중 ep35 기준으로 ep34 이전에 발행된 글들은 tag 필드를 아예 넣지 않았거나, 넣었더라도 TAG_ID_MAP에 등록된 공식 태그가 아닌 임의 태그를 쓴 경우가 많다. 미등록 태그는 resolve_tag_ids() 함수에서 조용히 무시된다.

⚙️ 코드 위치: src/publish.py — resolve_tag_ids 함수

def resolve_tag_ids(tag_names: list[str]) -> list[int]:
    ids = []
    for name in tag_names or []:
        tag_id = TAG_ID_MAP.get(str(name).strip())
        if tag_id:
            ids.append(tag_id)
        else:
            print(f"      ⚠️ 미등록 태그 무시: {name} (TAG_ID_MAP에 없음)")
    return ids

태그가 없는 글은 WordPress 태그 아카이브 페이지에 노출되지 않는다. 검색엔진이 관련 콘텐츠를 묶어서 평가할 때 연결고리가 없는 셈이다. 34편 중 태그가 제대로 달린 글이 몇 편이나 될까 세어보면, ep34 이후로 발행된 것 한 편뿐이다. 33편이 태그 없이 살아있다.

파이프라인에 태그 강제 로직을 달았지만, 기존 33편의 태그 공백은 코드 수정만으로는 해결되지 않는다. WordPress REST API PATCH 요청으로 소급 적용하는 작업이 별도로 필요하다.


허점 2 — 본문 길이 검증 기준이 너무 낮다

publish_draft.pyload_draft() 함수를 보면 본문 길이를 검사하는 코드가 있다.

문제는 기준값이 500이라는 점이다. 우리 WRITING_GUIDE.md가 요구하는 기준은 HTML 태그 제외 순수 텍스트 2500자 이상이다. 그런데 검증 로직은 이걸 확인하지 않는다.

게다가 계산 방식 자체도 엄밀하지 않다. 현재 코드는 이렇게 돼 있다.

plain_len = len("".join(draft["content"].split()))

공백을 제거하고 이어 붙인 전체 문자열 길이를 측정하는데, HTML 태그(<p>, <div>, <h2> 같은 것들)가 포함된 채로 센다. <div style="background: #f8f9fa; border: 1px solid..."> 같은 스타일 속성 하나가 수십 자를 먹는다. 실제 독자가 읽는 글자 수는 이 숫자보다 훨씬 적다.

실제로 어떤 영향이 있었냐 하면, 초기 글들 중 일부는 지금 기준으로 읽어보면 텍스트가 얇다는 느낌이 든다. 서론-본론-결론 구조를 갖추고 있지만 각 섹션이 짧고, 코드 블록이나 표가 글자 수를 부풀린 경우가 있었다. 500자 게이트는 사실상 아무 글이나 통과시키는 수준이다. 오탈자 수준의 글도 문장 몇 개만 있으면 500자는 넘는다.

💡 팁: HTML 태그를 제거하고 실제 텍스트 길이를 재는 방법은 간단하다. Python의 re.sub(r'<[^>]+>', '', html)으로 태그를 걷어낸 뒤 공백 정규화해서 길이를 세면 된다. 지금 검증 로직에 이걸 넣으면 실제 텍스트 기준으로 게이트를 걸 수 있다.

검증 임계값 500은 “에러 방지”를 위한 안전망이지, “품질 보장”을 위한 기준이 아니다. 두 가지를 혼동하고 있었다.


허점 3 — excerpt 내용은 검증하지 않는다

publish_draft.pyREQUIRED_FIELDS를 보면 excerpt이 포함돼 있다.

REQUIRED_FIELDS = ["episode", "title", "excerpt", "category", "category_id", "seo_title", "meta_description", "focus_keyword", "threads_text"]

검증 로직은 이렇다.

missing = [k for k in REQUIRED_FIELDS if not draft.get(k)]

필드가 존재하고 빈 문자열이 아니면 통과다. “이 글은 시리즈 35편입니다”라고 써도, “블로그 자동화에 관한 글입니다”라고 써도 통과한다. WRITING_GUIDE.md에는 “시리즈 안내 문구 절대 금지, 본문 핵심만”이라고 명시돼 있지만, 코드는 그걸 전혀 강제하지 않는다.

초기 글들의 excerpt을 확인해보면 패턴이 보인다. “이 글은 devYul의 AI 자동화 부업 시리즈 N편입니다. 이번 편에서는…”으로 시작하는 excerpt가 꽤 있다. 검색 결과 스니펫에 이런 문구가 뜨면 클릭할 이유가 없다. 어떤 블로그든 시리즈 N편이라는 건 독자에게 아무 정보가 아니다.

구글 검색 결과에서 excerpt은 메타 디스크립션으로 쓰인다. 클릭률(CTR)에 직접 영향을 주는 필드인데, 34편 중 상당수가 이 부분을 낭비하고 있었다.

💡 팁: excerpt 검증에 “시리즈” 또는 “N편”이라는 단어가 포함되면 경고를 띄우는 로직을 추가하면 최소한의 방어는 된다. 완벽한 자동 검증은 어렵지만, 최악의 패턴은 간단한 문자열 매칭으로 잡을 수 있다.

REQUIRED_FIELDS는 “필드가 존재하는가”를 검사할 뿐, “필드가 제 역할을 하는가”는 검사하지 않는다. 두 가지는 전혀 다른 문제다.


점검 결과 요약 — 지금 할 수 있는 것과 없는 것

세 가지 허점 중 코드로 해결할 수 있는 건 두 번째와 세 번째다. 본문 길이 검증 임계값을 올리고 HTML 태그를 실제로 제거해서 측정하는 방식으로 바꾸는 건 publish_draft.py 한 파일 수정으로 끝난다. excerpt 경고 로직도 마찬가지다. 새로 발행되는 글부터는 이 기준을 강제할 수 있다.

문제는 첫 번째다. 태그 소급 적용은 코드 수정이 아니라 WordPress REST API를 통해 기존 포스트를 PATCH 요청으로 업데이트하는 작업이다. 34편 각각에 어떤 태그가 맞는지 판단하고, 해당 태그 ID를 포스트에 달아주는 스크립트를 짜야 한다. TAG_ID_MAP의 13개 태그와 published.json의 발행 기록을 기반으로 매핑 작업을 해야 한다.

그리고 솔직히 말하면, 세 번째 허점도 코드 수정이 새로운 글에만 효과가 있다. 기존 34편 중 excerpt이 잘못된 글들은 WordPress 편집기에서 직접 고쳐야 한다. 자동화 블로그를 운영하면서 과거 글을 수동으로 고치는 아이러니가 있다.

허점 해결 방법 영향 범위
태그 미적용 (33편) PATCH 스크립트 작성 후 소급 적용 기존 33편 전체
본문 길이 검증 기준 미흡 publish_draft.py 수정 (임계값 올리기, 태그 제거 후 측정) 새로 발행되는 글부터
excerpt 내용 미검증 publish_draft.py 경고 로직 추가 + 기존 글 수동 수정 신규: 자동 / 기존: 수동

이 점검을 하면서 깨달은 것이 있다. 파이프라인 자동화를 믿고 있었는데, 자동화는 결국 내가 만든 기준만큼만 작동한다. 기준이 허술하면 자동화는 허술한 일을 빠르게 할 뿐이다. 34편을 빠르게 쌓은 건 자랑인데, 그 34편의 품질 기준이 모호했다면 빠르게 쌓은 것 자체가 문제가 된다.

애드센스 재심사를 신청하기 전에 이 세 가지를 먼저 처리해야 한다. 코드 수정은 오늘 바로 할 수 있고, 태그 소급 적용 스크립트는 내일 안에 만들 수 있다. 기존 글 excerpt 수정은 우선순위를 정해서 가장 약한 것들부터 고치는 게 현실적이다.

자동화 시스템의 품질은 가장 허술한 검증 로직 수준을 넘지 못한다. 나는 이번 점검에서 내 검증 로직이 얼마나 허술했는지 직접 확인했다.


마치며 — 재심사 신청은 이 작업을 끝낸 뒤로

ep33에서 애드센스 탈락 경험을 쓰고, ep34에서 파이프라인 코드를 손봤고, ep35인 오늘은 기존 34편의 실제 상태를 점검했다. 세 편이 하나의 흐름이다. 이 흐름이 끝나야 재심사 신청을 할 수 있다.

급하게 신청하고 싶은 마음이 없는 건 아니다. 그런데 ep33에서 탈락한 이유 중 하나가 “충분히 준비되지 않은 상태에서 신청했다”는 거였다. 같은 실수를 반복하고 싶지 않다. 이번에는 점검 → 보완 → 신청 순서를 지킬 것이다.

다음 편에서는 실제로 태그 소급 적용 스크립트를 만들고, 기존 글들의 excerpt을 수정하는 작업을 기록할 예정이다. WordPress REST API PATCH 요청으로 발행된 글을 어떻게 일괄 업데이트하는지, 실제 코드와 함께 쓸 것이다.

📌 다음 편: 34편 소급 보완 실전 — 태그 일괄 적용과 excerpt 수정 작업 기록

  • WordPress REST API로 기존 포스트 태그 일괄 수정하는 스크립트 작성
  • 발행된 글의 excerpt 패턴 분석 — 어떤 글이 가장 나쁜 상태인가
  • 코드 수정 후 본문 길이 검증 로직 개선 실제 diff

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top