website 로 분류된 URL 을 ContentInput 으로 옮기는 규칙. 도메인마다 따로 쓰지 않고 패턴 7개로 묶었다.
도메인 124개를 일곱 패턴으로 묶었다. 도메인마다 규칙을 쓰면 124개가 되고 사이트가 리뉴얼할 때마다 하나씩 조용히 틀어진다. 패턴으로 묶으면 규칙이 일곱 개이고, 새 도메인이 와도 배정만 하면 된다.
패턴 × 채우는 칸 · 규모
링크 수는 그 패턴에 속한 도메인들이 받은 토큰 링크의 합이다. 절반은 그 패턴 안에서도 도메인마다 갈린다는 뜻이다.
| 패턴 | 도메인 | 링크 | 비중 | text.primary | text.body | publishedAt | mediaUrls[0] | tags[] |
|---|---|---|---|---|---|---|---|---|
| P1 article 제목과 요약이 이 페이지 것이고 발행시각도 있다 | 41 | 616 | 27.8% | 채운다 | 채운다 | 채운다 | 채운다 | 절반 |
| P2 entry 제목과 요약이 이 페이지 것인데 발행시각이 없다 | 31 | 432 | 19.5% | 채운다 | 채운다 | — | 채운다 | — |
| P3 title-only 제목만 쓸 만하고 요약은 없거나 일반 문구다 | 13 | 171 | 7.7% | 채운다 | — | — | 절반 | — |
| P4 site-wide 값이 있으나 그 페이지가 아니라 사이트 전체를 설명한다 | 28 | 871 | 39.3% | — | — | — | — | — |
| P5 gated 응답이 로그인 요구 · 페이월 · 봇 차단 안내문이다 | 4 | 66 | 3.0% | — | — | — | — | — |
| P6 spa 클라이언트 렌더라 메타가 구조상 비었다 | 2 | 12 | 0.5% | — | — | — | — | — |
| P7 unfilled 템플릿을 깔고 내용을 안 채웠다 | 5 | 48 | 2.2% | — | — | — | — | — |
쓸 수 있는 구간은 1,219건, 전체의 55.0% 다. 나머지 997건은 값이 있어도 그 페이지를 말하지 않는다.
가장 큰 손실은 P4 site-wide 로 링크 871건(39.3%)이다. 도메인은 28개뿐인데 링크가 몰려 있다 — facebook.com 186 · coincommunities.org 144 · truthsocial.com 79 · google.com 66 처럼 대형 도메인이 여기 모여 있어서다.
추출기는 하나다. 도메인을 보고 분기하지 않는다. 받은 값을 보고 패턴을 판정하고, 필드마다 정해진 순서로 표준을 훑는다.
HTML 한 장에서 ContentInput 까지
왼쪽은 값을 모으는 단계이고 오른쪽은 그 값이 쓸 만한지 판정하는 단계다. 판정이 뒤에 오는 것이 중요하다 — 값을 다 모아야 “있는데 사이트 공통 문구” 인지 알 수 있다.
이것이 이번 배정에서 나온 가장 실무적인 결과다. 하나의 폴백 체인을 쓰면 안 된다. text 는 OpenGraph 가 압도하는데 published 는 JSON-LD 가 이긴다.
필드별 폴백 체인
순서는 짐작이 아니라 P1 배정 41개 도메인에서 실제로 그 값을 준 표준의 빈도로 정했다. 오른쪽이 그 빈도다.
| 출력 칸 | 시도 순서 | P1 실측 빈도 |
|---|---|---|
text.primary | og:title → jsonld:headline → meta:title → twitter:title | og:title 35 · jsonld:headline 5 |
text.body | og:description → jsonld:articleBody → meta:description → twitter:description | og:description 33 · jsonld:articleBody 4 |
publishedAt | jsonld:datePublished → article:published_time | jsonld:datePublished 32 · article:published_time 9 |
mediaUrls[0] | og:image → jsonld:image | og:image 39 |
tags[] | jsonld:keywords → article:tag | jsonld:keywords 13 |
🔴 패턴은 도메인에 고정하지 않는다. 같은 도메인인데 URL 경로에 따라 패턴이 갈리는 경우가 19건 나왔다. fomo.family 는 프로필 페이지가 site-wide 인데 블로그 글은 article 이고, whitehouse.gov 는 기사가 article 인데 PDF 링크는 메타가 아예 없다.
그래서 §4 의 도메인별 배정은 기대값이자 검수용이고, 런타임 판정은 항상 그 URL 에서 실제로 받은 값으로 한다. 도메인 표를 믿고 분기하면 이 19건이 조용히 틀린다.
여기까지가 원래 규격이었다. 그런데 dailymail.com 기사 하나를 실제로 열어보고 규격이 바뀌었다. 그 페이지는 OpenGraph 가 통째로 비어 있는데 피드에는 제목과 요약과 발행시각이 다 있었다.
기사 페이지 899KB RSS 항목
og:title 없음 title Andy Burnham says high streets…
og:desc 빈 문자열 desc The Prime Minister has pledged…
pub_time 없음 date Mon, 10 Aug 2026 22:09:40 GMTdailymail.com 은 배정에서 P3 title-only 였다. OpenGraph 가 비어 제목만 겨우 건졌기 때문이다. 피드를 보면 P1 으로 올라간다.
피드를 실제로 열어본 결과
태그가 있다고 피드인 것이 아니다. 단일 페이지 앱은 어떤 경로를 넣어도 200 과 함께 앱 껍데기를 돌려주므로, 열어서 파싱까지 해봐야 안다. 이득 표시는 OpenGraph 가 약한 패턴이라 피드가 실제로 보탬이 되는 도메인이다.
| 도메인 | 패턴 | 항목 | 시간창(일) | 요약 있는 항목 |
|---|---|---|---|---|
trib.al | P1 | 150 | 283 | 150/150 |
yegge.ai | P2 | 20 | 278 | 20/20 |
forbes.com | P2 | 11 | 94 | 10/11 |
longdog.lol | P7 | 1 | 62 | 1/1 |
animamacau.org 이득 | P3 | 10 | 54 | 10/10 |
dailymail.com 이득 | P3 | 150 | 41 | 150/150 |
littlepoe.lol | P7 | 1 | 14 | 1/1 |
pumpga.fun | P7 | 1 | 12 | 1/1 |
sciencedaily.com | P2 | 60 | 6 | 60/60 |
space.com | P1 | 50 | 5 | 50/50 |
digitalcameraworld.com | P1 | 50 | 5 | 49/50 |
tumblr.com 이득 | P4 | 20 | 4 | 18/20 |
태그가 있던 도메인 34개 중 실제 피드는 24개이고, 요약까지 있는 것은 22개다. 나머지는 parse-fail 2 · html-shell 2 · empty-feed 2 · HTTP 404 2 였다.
시간창이 값어치를 정한다. 중앙값은 5일인데 사이트마다 자릿수가 다르다 — trib.al 283일 · dailymail 41일 · knowyourmeme 3일 · foxnews 0일. 피드는 최근 목록이라, 링크를 받은 직후에 부르면 들어 있고 몇 주 뒤에 부르면 없다.
그래서 배치 재수집에서는 거의 쓸모가 없고 실시간 수집에서는 유효하다. 실제 파이프라인은 token.flow 이벤트를 실시간으로 받으므로 토큰이 방금 건 기사는 대개 피드 안에 있다.
그래서 규칙
전량이 아니라 결측 보정이다. 조건을 붙이는 이유는 호출 때문이다.
① OG 폴백 체인을 먼저 돌린다
② text_body 또는 published 가 비었나?
아니오 → 끝. RSS 를 부르지 않는다 (P1 · P2 는 여기서 끝난다)
예 → ③
③ 그 도메인에 rel=alternate rss 링크가 있나?
아니오 → 끝
예 → ④
④ 피드를 받아 항목 link 를 이 URL 과 대조한다
맞는 항목 있음 → title · description · pubDate 로 빈 칸을 메운다
없음 → 끝. 비운 채로 둔다“추가 호출 0회” 원칙이 여기서 깨진다. 그래서 조건을 좁혔다.
⚠️ 적중률은 아직 못 쟀다. 지금 데이터는 링크를 받은 지 6주가 지난 것이라 피드에서 이미 밀려났고, 실시간 조건의 적중률은 파이프라인에 붙여야 나온다.
패턴마다 어떻게 판정하고, 무엇이 어디로 가고, 실측 값이 어떻게 생겼는지다.
| 출력 칸 | 이 패턴에서의 출처 | 채워진 도메인 |
|---|---|---|
text.primary | og:title → jsonld:headline → meta:title | 41/41 |
text.body | og:description → jsonld:articleBody → meta:description | 41/41 |
publishedAt | jsonld:datePublished → article:published_time | 41/41 |
mediaUrls[0] | og:image → jsonld:image | 40/41 |
tags[] | jsonld:keywords → article:tag | 21/41 |
밈마다 제목·요약·이미지·키워드가 다르고 jsonld datePublished 에 실제 등록일이 있다.
| 출력 칸 | 이 패턴에서의 출처 | 채워진 도메인 |
|---|---|---|
text.primary | og:title → meta:title | 31/31 |
text.body | og:description → meta:description → jsonld:headline | 31/31 |
publishedAt | jsonld:datePublished | 1/31 |
mediaUrls[0] | og:image | 25/31 |
tags[] | meta:keywords | 6/31 |
앱마다 제목·설명은 다르지만 발행일은 전혀 없고 이미지는 'Placeholder.mill'이라는 미렌더링 자리표시자다.
| 출력 칸 | 이 패턴에서의 출처 | 채워진 도메인 |
|---|---|---|
text.primary | og:title → meta:title → jsonld:headline | 13/13 |
text.body | og:description → meta:description | 4/13 |
publishedAt | jsonld:datePublished → article:published_time | 4/13 |
mediaUrls[0] | og:image → jsonld:image | 8/13 |
tags[] | meta:keywords | 1/13 |
og는 완전히 비어 있고 jsonld headline만 기사별로 다르며 본문은 'READ MORE:' 같은 무의미한 값이라 요약이 없다.
text.body 는 비운다| 출력 칸 | 이 패턴에서의 출처 | 채워진 도메인 |
|---|---|---|
text.primary | og:title → meta:title | 27/28 |
text.body | og:description → meta:description | 25/28 |
publishedAt | jsonld:datePublished | 3/28 |
mediaUrls[0] | og:image | 22/28 |
tags[] | meta:keywords | 2/28 |
두 토큰 페이지 모두 og/jsonld/meta 값이 완전히 동일하며 해당 토큰이 아니라 Pump.fun 플랫폼 전체를 설명한다.
| 출력 칸 | 이 패턴에서의 출처 | 채워진 도메인 |
|---|---|---|
text.primary | og:title → meta:title | 4/4 |
text.body | meta:description → og:description | 2/4 |
publishedAt | — | 0/4 |
mediaUrls[0] | og:image | 2/4 |
tags[] | — | 0/4 |
단축 URL이 인스타그램 로그인 요구 페이지로 리다이렉트되어 값이 전부 로그인 유도 문구다.
unseen 으로 기록| 출력 칸 | 이 패턴에서의 출처 | 채워진 도메인 |
|---|---|---|
text.primary | meta:title | 1/2 |
text.body | meta:description | 1/2 |
publishedAt | — | 0/2 |
mediaUrls[0] | — | 0/2 |
tags[] | — | 0/2 |
spa=true 이고 og:title/og:description 이 둘 다 비어 있어 R2 에 해당하며 meta 필드도 사용자명만 바뀌는 프로필 템플릿이라 실질 정보가 없다
unseen 으로 기록| 출력 칸 | 이 패턴에서의 출처 | 채워진 도메인 |
|---|---|---|
text.primary | meta:title | 4/5 |
text.body | meta:description | 1/5 |
publishedAt | — | 0/5 |
mediaUrls[0] | — | 0/5 |
tags[] | — | 0/5 |
워드프레스 기본 설치 그대로라 meta 제목만 사이트명이고 og/jsonld/설명/이미지가 전부 비어 있다
placeholder 로 기록. 결측 자체가 신호다G-6 이 “계약된 필드를 채우는 것을 보장하거나 아예 만들지 않는다” 로 껍데기 객체를 금지한다. 그런데 못 채우는 이유가 넷이고, 넷의 뜻이 서로 다르다.
못 채울 때 무엇을 남기나
셋은 “정보가 없다” 이고 하나는 “정보가 있다” 다. 넷을 한 값으로 접으면 마지막 하나를 잃는다.
| 상황 | Content | 무엇을 남기나 | 왜 |
|---|---|---|---|
| P4 사이트 공통 문구 | 안 만든다 | site_wide | 값을 넣으면 같은 문구가 수백 행에 복제된다. coincommunities.org 144개 토큰이 전부 같은 Pump.fun 소개문을 갖게 된다 |
| P5 로그인벽 · 봇 차단 | 안 만든다 | gated | 대상 쪽 사정이라 재시도로 풀릴 수 있다. 영구 실패와 구분해야 한다 |
| P6 SPA | 안 만든다 | unseen | 구조상 못 본 것이지 없는 것이 아니다. server 필드를 남긴 이유가 이 구분이다 |
| P7 템플릿 미기입 | 안 만든다 | placeholder 🔴 | 이것만 신호다. 채울 자리를 만들어 놓고 안 채웠다는 뜻이라, 소유권 조사에서 CA 를 안 채운 도메인 집단과 정확히 겹쳤다 |
결측을 하나로 접으면 안 되는 이유가 실측으로 확인됐다. 컨텐츠 조사에서 text 가 “있지만 쓸모없음” 으로 판정된 토큰사이트가 longdog.lol · pumpga.fun · littlepoe.lol · crypto.grok.me · darkarena.app 인데, 이것은 앞서 소유권 조사에서 계약 주소를 안 채운 것으로 나온 바로 그 도메인들이다.
두 조사는 서로를 몰랐다. 그런데 같은 집단을 가리켰다. 템플릿을 깔고 내용을 안 채운 사이트는 계약 주소도 메타데이터도 안 채운다. 이 결측을 absent 로 뭉개면 그 신호가 사라진다.
tags 는 P1 에서만 시도한다. P1 안에서도 실제로 채워지는 것은 21/41 이고, P2 이하에서는 거의 전부 사이트 공통 분류 라벨이었다. 판정한 에이전트들이 “site-wide category labels, not topics” 를 반복해 지적했다.text.body 는 요약으로 충분하다고 본다. JSON-LD articleBody 로 본문 전문이 오는 곳은 11개 도메인이고 전부 뉴스사다. 나머지는 og:description 의 요약뿐인데, “이 링크가 무슨 주제인가” 라는 목적에는 그것으로 충분하다.병렬 작업자 아홉이 같은 결론에 도달해야 해서, 판정을 순서가 있는 캐스케이드로 고정했다. 먼저 걸리는 규칙에서 멈춘다.
판정 캐스케이드와 실제 적용 횟수
못 쓰는 경우를 먼저 걸러내고 쓸 수 있는 것만 등급을 매긴다. 순서를 뒤집으면 로그인 안내문이 “제목과 요약이 다 있다” 로 읽혀 P1 에 들어간다.
| 순서 | 조건 | 결과 | 적용 |
|---|---|---|---|
| R1 | og · twitter · meta 값이 로그인 요구 · 페이월 · 봇 차단 · 쿠키 동의 문구인가 | P5 | 4 |
| R2 | spa 가 true 이고 og 제목·설명이 둘 다 비었나 | P6 | 2 |
| R3 | 미기입 표식이 남았거나, 토큰사이트인데 설명이 홈 카피 그대로인가 | P7 | 5 |
| R4 | 값이 이 페이지가 아니라 사이트 전체를 설명하는가 | P4 | 22 |
| R5a | 제목과 요약이 둘 다 이 페이지 것이고 발행시각도 있다 | P1 | 41 |
| R5b | 제목과 요약이 둘 다 이 페이지 것인데 발행시각이 없다 | P2 | 31 |
| R6 | 제목만 이 페이지 것이고 요약은 없거나 일반 문구다 | P3 | 13 |
| R7 | 어디에도 안 맞는다 — 가장 보수적인 쪽으로 | P4 | 6 |
샘플이 두 개인데 서로 다른 패턴으로 보이면 더 나쁜 쪽을 택하게 했다. 낙관 쪽으로 기울면 구현할 때 빈 필드가 나온다. 그렇게 갈린 것이 19건이다.
확신도는 high 86 · medium 28 · low 10 였다. low 10건은 대부분 한 도메인에 성격이 다른 URL 이 섞인 경우이고, §2 의 “패턴을 도메인에 고정하지 않는다” 가 그 대응이다.
이 배정의 한계 셋.
첫째, 도메인당 URL 을 1~2개만 봤다. 그 도메인의 나머지 URL 도 같은 모양일 것이라는 추정이다. 뉴스사처럼 기사마다 다른 곳은 샘플 하나가 대표할 뿐이다.
둘째, 124 도메인만 배정했다. 조사 대상 180개 중 56개는 403 봇 차단으로 못 열었고, 공유 도메인 797개 전체로 보면 더 적다.
셋째, 판정 시점이 2026-08-11 이다. 사이트는 리뉴얼되고 메타는 바뀐다. 다만 표준 8종은 사이트가 유지할 유인이 따로 있어(검색 리치결과 · SNS 공유 미리보기) CSS 셀렉터보다 훨씬 오래 간다 — 그것이 표준만 보기로 한 이유다.
배정 데이터는 scaffold/website-patterns.json, 실측 원문은 scaffold/website-extract-samples.json, 이 페이지를 만드는 것은 scaffold/render-website-content-mapping.py 다.