같은 소재를 여러 곳에 올렸더니 문장이 겹쳤습니다 — AI콘텐츠 중복 재는 법
같은 소재로 여러 채널에 AI콘텐츠를 만들어 올렸습니다. 블로그자동화로 돌리다 보니 어느 순간 문장까지 겹치기 시작했습니다.
재료가 같으니 당연한 결과였습니다. 사실은 같아야 하지만 문장까지 같을 이유는 없습니다.
1. 겹침을 숫자로 잽니다 2. 기준을 넘으면 발행을 막습니다 3. 채널마다 쓰는 각도를 다르게 잡습니다 4. 기록은 발행에 성공한 뒤에만 남깁니다
AI콘텐츠 증상 — 문장이 그대로 겹칩니다
증상 — 채널이 다른데 같은 문장이 여러 곳에 올라가 있습니다.

원인 — 같은 자료를 같은 방식으로 요약하게 시키면 비슷한 문장이 나옵니다. 생성 쪽에서 보면 가장 자연스러운 표현을 고르는 것이라, 매번 같은 답에 수렴합니다.
프롬프트에 "다르게 써라" 를 넣어도 한계가 있었습니다. 재료가 같으면 결국 비슷해집니다.
저는 처음에 이걸 온도값 같은 설정으로 풀어 보려 했습니다. 표현이 다양해지긴 했는데, 대신 문장이 어색해지는 경우가 늘었습니다. 다양성과 품질을 맞바꾸는 셈이라 그만뒀습니다.
그다음엔 "앞서 쓴 글과 다르게 써라" 면서 이전 글을 같이 넣어 봤습니다. 이건 어느 정도 됐는데, 채널이 늘수록 넣을 것이 길어져서 관리가 어려웠습니다.
블로그자동화에서 겹침을 숫자로 재기
해결 — 눈으로 판단하지 말고 재서 기준을 정합니다.
단어 네 개짜리 묶음을 만들어 두 글이 얼마나 겹치는지 봅니다.
def shingles(text: str, n: int = 4) -> set:
words = re.findall(r"[가-힣A-Za-z0-9]+", text)
return {" ".join(words[i:i+n]) for i in range(len(words) - n + 1)}
def overlap(a: str, b: str) -> float:
"""자카드 유사도 — 겹치는 묶음 / 전체 묶음"""
sa, sb = shingles(a), shingles(b)
if not sa or not sb:
return 0.0
return len(sa & sb) / len(sa | sb)

| 수치 | 판정 |
|---|---|
| 0.02 | 거의 안 겹침 — 통과 |
| 0.18 | 일부 겹침 — 통과 |
| 0.34 | 많이 겹침 — 차단 |
단어 네 개로 묶는 이유가 있습니다. 두 개면 흔한 조합이 다 걸리고, 여섯 개면 조사 하나만 달라도 안 잡힙니다. 넷이 제 경우엔 적당했습니다.
기준값은 내부 판단입니다
주의 — 여기를 오해하기 쉽습니다. 제가 쓰는 기준은 검색엔진이 공개한 수치가 아닙니다.
검색엔진이 "이 값을 넘으면 불이익" 이라고 밝힌 적은 없습니다. 제 기준은 복붙을 잡기 위한 내부 휴리스틱입니다.
| 이 값을 넘으면 검색 순위가 내려간다 | ❌ 그런 근거 없습니다 |
| 이 값을 넘으면 표현을 너무 재사용한 것이다 | ✅ 이 뜻입니다 |
기준을 정할 때는 실제 사례를 몇 개 재보고 정했습니다. 눈으로 봐서 "이건 너무 비슷하다" 싶은 것들의 수치를 확인하고 그 언저리로 잡았습니다.
사실 자체는 겹쳐도 됩니다. 가격이 같고 구성이 같은 건 당연합니다. 막아야 하는 건 표현과 구성의 재사용입니다.
근본 해결 — 채널마다 각도를 다르게
숫자로 막는 건 안전망입니다. 1차 방어는 애초에 다르게 쓰는 것입니다.
| 채널 | 각도 |
|---|---|
| 정보 사이트 | 문제 해결 절차 중심 |
| 개인 블로그 | 직접 써본 경험 중심 |
| 짧은 글 채널 | 핵심 한 가지만 |
| 판매 채널 | 구성·조건 안내 중심 |
각도가 다르면 같은 재료로도 다른 문장이 나옵니다. 저는 채널별로 이 각도를 파일에 적어 두고 생성할 때 넣습니다.
실측으로는 각도를 나눈 뒤 겹침 수치가 눈에 띄게 떨어졌습니다. 제가 확인한 조합에서는 0.02 수준까지 내려갔습니다. 같은 상품 이야기인데 읽어 보면 완전히 다른 글입니다.
대안으로 아예 채널마다 다른 소재를 쓰는 방법도 있습니다. 다만 그러면 만들 것이 배로 늘어납니다. 저는 각도를 나누는 쪽이 현실적이었습니다.
함정 — 기록 시점
여기서 한 번 걸렸습니다. 생성하자마자 기록하게 만들어 뒀습니다.

증상 — 발행에 실패한 글이 기록에 남아서, 다음 채널이 존재하지도 않는 글과 비교하고 있었습니다.
원인 — 생성 시점에 기록했기 때문입니다. 그 뒤에 게이트에서 막히거나 발행이 실패해도 기록은 남습니다.
해결 — 게이트를 통과하고 발행에 성공한 뒤에만 기록합니다.
if not gates_ok(post):
return # 기록하지 않는다
if not publish(post):
return # 여기서도 기록하지 않는다
registry.add(post.product_id, post.channel, post.body) # 성공한 뒤에만
이 순서를 안 지키면 겹침 판정이 실제와 어긋납니다. 없는 글 때문에 새 글이 막히는 일이 생깁니다.
확인 못 한 것
기준값이 실제로 적당한지는 확인하지 못했습니다. 지금 값으로 막힌 글을 사람이 보면 대체로 납득이 가는데, 그게 최적인지는 모릅니다.
더 낮추면 정상 글이 막히고 더 높이면 복붙이 통과할 텐데, 그 경계를 숫자로 확인해 보지는 않았습니다. 사례가 더 쌓이면 다시 볼 생각입니다.
판정 — 계속 쓴다
숫자로 재는 방식은 잘 돌아갑니다. 눈으로 판단하는 것과 달리 결과가 일정합니다.
각도를 나누는 것이 더 근본적입니다. 검사로 막는 것보다 애초에 다르게 나오게 하는 쪽이 낫습니다.
기준값이 근거 있는 수치인 척하지 않는 것도 중요합니다. 내부 판단이라고 밝혀 두면 나중에 조정하기도 쉽습니다.
직접 하실 분께
하나. 겹침은 숫자로 재세요. 눈으로는 매번 다르게 판단하게 됩니다.
둘. 기준값이 어디서 나온 것인지 적어 둡니다. 근거 없는 수치를 근거 있는 것처럼 쓰면 나중에 못 고칩니다.
셋. 채널마다 각도를 정해 둡니다. 이게 1차 방어입니다.
넷. 기록은 발행에 성공한 뒤에만 남깁니다. 순서가 틀리면 판정이 어긋납니다.
다음에는 기준값을 사례로 검증해서 적당한 선을 숫자로 잡아보려고 합니다. 되면 이어서 적겠습니다.