WordPress 발행 중복 방지, published_log와 Jaccard 교차 체크로 구현하는 법

자동화로 블로그 글을 발행하다 보면 어느 순간 같은 주제의 글이 두 번, 세 번 올라가는 상황이 생깁니다. 제목이 조금 다르더라도 내용이 거의 똑같은 글이 발행되면 검색 엔진 입장에서도 좋지 않고, 독자 입장에서도 신뢰를 잃습니다. WordPress 발행 중복 방지를 위해 published_log와 Jaccard 유사도 교차 체크를 조합하면 이 문제를 구조적으로 막을 수 있습니다.

왜 단순 제목 비교만으로는 부족한가

WordPress 발행 중복 방지

가장 단순한 중복 방지 방법은 발행된 글의 제목 목록을 저장해두고, 새 글 제목이 그 목록에 있으면 건너뛰는 방식입니다. 그런데 이 방식에는 명확한 한계가 있습니다.

제목이 조금만 달라져도 중복을 감지하지 못합니다. 예를 들어 “Claude API 연결 방법”과 “Claude API 연동하는 법”은 완전히 다른 문자열이지만 내용은 거의 동일할 수 있습니다. 단순 문자열 비교로는 이런 경우를 걸러낼 수 없습니다.

이 문제를 해결하는 방법이 바로 Jaccard 유사도(Jaccard Similarity)를 활용한 교차 체크입니다. 두 텍스트가 공유하는 단어의 비율을 수치로 계산해서, 일정 기준 이상이면 중복으로 판단하는 방식입니다.

published_log 구조 설계

published_log는 발행된 글의 핵심 정보를 저장하는 로그 파일 또는 데이터베이스 테이블입니다. 이 로그에 무엇을 저장하느냐에 따라 중복 감지의 정확도가 달라집니다.

최소한 다음 항목을 포함하는 것이 적합합니다.

  • post_id: WordPress에서 발행된 글의 고유 ID
  • title: 발행 당시의 제목 원문
  • title_tokens: 제목을 단어 단위로 분리한 집합 (Jaccard 계산용)
  • published_at: 발행 일시
  • slug: URL 슬러그 (보조 중복 체크용)

title_tokens를 별도로 저장해두면, 새 글 발행 시마다 제목을 다시 토크나이징(tokenizing, 텍스트를 단어 단위로 분리하는 작업)할 필요 없이 저장된 집합과 바로 비교할 수 있어서 처리 속도가 빠릅니다.

published_log 구조 예시

Jaccard 유사도로 제목 교차 체크하는 방법

Jaccard 유사도는 두 집합 A와 B가 있을 때, 교집합의 크기를 합집합의 크기로 나눈 값입니다.

Jaccard(A, B) = |A ∩ B| / |A ∪ B|

예를 들어 기존 제목 “Claude API 연결 방법 정리”와 새 제목 “Claude API 연동하는 방법”을 각각 단어 집합으로 만들면 다음과 같습니다.

구분 단어 집합
기존 제목 A {Claude, API, 연결, 방법, 정리}
새 제목 B {Claude, API, 연동하는, 방법}
교집합 A ∩ B {Claude, API, 방법} → 3개
합집합 A ∪ B {Claude, API, 연결, 방법, 정리, 연동하는} → 6개
Jaccard 유사도 3 / 6 = 0.5 (50%)

유사도 임계값(threshold)을 0.5로 설정하면 이 경우 중복으로 판단해 발행을 차단합니다. 임계값은 콘텐츠 성격에 따라 0.4~0.6 사이에서 조정하는 것이 일반적입니다.

Python으로 구현하는 교차 체크 로직

실제 구현은 Python 기준으로 아래와 같이 작성할 수 있습니다.

def tokenize(title):
    return set(title.lower().split())

def jaccard_similarity(set_a, set_b):
    intersection = set_a & set_b
    union = set_a | set_b
    if not union:
        return 0.0
    return len(intersection) / len(union)

def is_duplicate(new_title, published_log, threshold=0.5):
    new_tokens = tokenize(new_title)
    for entry in published_log:
        stored_tokens = set(entry["title_tokens"])
        score = jaccard_similarity(new_tokens, stored_tokens)
        if score >= threshold:
            return True, entry["title"], score
    return False, None, 0.0

이 함수는 published_log에 저장된 모든 기존 제목과 새 제목을 비교해서, 유사도가 임계값 이상인 항목이 하나라도 있으면 True를 반환합니다. 발행 파이프라인에서 이 값이 True이면 해당 글을 건너뛰거나 사람이 확인할 수 있도록 별도 큐에 보내는 방식으로 활용합니다.

중복 체크 처리 흐름

WordPress 발행 파이프라인에 통합하는 방법

위 로직을 WordPress 자동 발행 파이프라인에 통합하는 순서는 다음과 같습니다.

  1. 새 글 제목 생성: 자동화 스크립트가 새 글 제목을 만든다.
  2. 중복 체크 실행: is_duplicate() 함수를 호출해 published_log와 비교한다.
  3. 분기 처리: 중복이면 건너뛰고 로그에 기록. 중복이 아니면 다음 단계로 진행한다.
  4. WordPress API 발행: WordPress REST API 또는 xmlrpc를 통해 글을 발행한다.
  5. published_log 업데이트: 발행 성공 후 제목, 토큰, 발행 일시를 published_log에 추가한다.

5번 단계에서 로그 업데이트를 빠뜨리면 중복 체크가 작동하지 않습니다. 발행 성공 응답을 받은 직후에 바로 저장하는 것이 중요합니다.

Jaccard 체크의 한계와 보완 방법

Jaccard 유사도는 단어 순서를 고려하지 않습니다. “방법 정리 Claude API”와 “Claude API 방법 정리”는 순서가 달라도 집합은 동일하기 때문에 유사도가 1.0으로 계산됩니다. 이 특성은 중복 감지에서는 오히려 유리하게 작동합니다.

반면 단어 자체가 달라지는 경우(동의어, 유사어)는 감지하지 못하는 한계가 있습니다. “방법”과 “방식”, “구현”과 “설정”처럼 의미는 같지만 단어가 다른 경우입니다. 이 한계를 보완하려면 형태소 분석기(예: konlpy의 Okt 또는 Mecab)로 단어를 어근(형태소) 단위로 분리하거나, 임계값을 조금 낮추는 방법을 함께 적용하는 것이 알려진 방식입니다.

체크 방식 장점 한계
단순 제목 일치 구현 단순 유사 제목 감지 불가
Jaccard 유사도 유사 제목 감지 가능, 빠른 연산 동의어 감지 불가, 단어 분리 방식에 따라 정확도 차이
형태소 분석 + Jaccard 한국어 특성 반영, 정확도 향상 형태소 분석기 설치 및 설정 필요

중복 체크 방식 비교

자주 묻는 질문

Q1. published_log는 어디에 저장하는 것이 좋습니까?
JSON 파일, SQLite, 또는 MySQL 테이블 어느 방식이든 사용 가능합니다. 글 수가 수백 개 미만이면 JSON 파일로도 충분하고, 수천 개 이상이면 데이터베이스 테이블로 관리하는 것이 조회 속도 면에서 유리합니다.

Q2. 임계값 0.5는 어떤 기준으로 정해진 것입니까?
0.5는 절반 이상의 단어를 공유하면 유사하다고 보는 기준입니다. 콘텐츠 주제가 겹칠 수밖에 없는 특정 분야(예: 기술 튜토리얼)에서는 0.6~0.65로 높이는 것도 방법입니다. 반대로 제목이 짧거나 단어 수가 적은 경우에는 0.4 정도로 낮추는 것을 검토할 수 있습니다.

Q3. 발행 후 로그 업데이트 중 오류가 나면 어떻게 됩니까?
글은 이미 발행됐는데 로그에 기록이 안 된 상황입니다. 이 경우 다음 발행 시 같은 제목이 다시 통과될 수 있습니다. 발행 성공 직후 로그 업데이트가 실패하면 별도 오류 파일에 기록해두고, 주기적으로 WordPress에서 실제 발행된 글 목록을 가져와 published_log를 동기화하는 보완 로직을 추가하는 것이 안전합니다.


WordPress 발행 중복 방지는 자동화 파이프라인이 길어질수록 반드시 필요한 체크 단계입니다. published_log 설계와 Jaccard 교차 체크를 함께 구성해두면, 제목이 조금 달라도 유사한 글이 반복 발행되는 상황을 구조적으로 막을 수 있습니다. 단순 문자열 비교에서 한 단계 더 나아간 방식으로, 자동화 블로그 운영의 품질 관리에 실질적인 도움이 됩니다.

썸네일: Markus Winkler on Unsplash

댓글 달기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다

위로 스크롤