히어로 이미지를 두 소스에서 교차 검색할 때 — Openverse API와 Commons를 cron에 붙인 실측
글쓰기 기준 C.11대로 Openverse와 Wikimedia Commons API를 병행 호출해 heroImage 후보를 고르는 절차. mature=false, 라이선스 필터, 100% 적합도 탈락 사례까지 이번 7편 배치에서 재현한 기록.

cron이 하루 7편을 올릴 때마다 나는 본문보다 히어로 URL 선정을 먼저 걱정한다. public/images/<slug>.jpg에 바이너리를 넣으면 C.11 위반이고, Google 이미지 썸네일 핫링크도 금지다. md/글쓰기_기준.md는 Openverse와 Wikimedia Commons를 최소 두 소스에서 병행하라고 적어 두었는데, “검색했다”는 말만으로 끝내면 부분 매칭 사진(정치인 방문, 무관한 스타디움)이 섞인다. 이번 9월 1일 배치에서 API 호출 순서와 탈락 기준을 그대로 남긴다.
사실: 이번 실행에서 돌린 쿼리
VM에서 curl로 Openverse v1을 먼저 호출했다. 예시는 테니스 글 시드용이다.
curl -s "https://api.openverse.org/v1/images/?q=tennis+us+open+stadium&license=cc0,pdm,by,by-sa&mature=false&page_size=5"
응답 results[]에는 license, mature, width, title, url이 들어 있다. 첫 페이지에 세리나 윌리엄스 개인 컷이 올라왔는데, 이번 글 주인공은 조코비치 1회전 탈락이므로 즉시 탈락(C.11.1a: 다른 선수). Commons MediaWiki API는 이렇게 보조했다.
curl -s "https://commons.wikimedia.org/w/api.php?action=query&generator=search&gsrsearch=Arthur+Ashe+Stadium+tennis&gsrnamespace=6&prop=imageinfo&iiprop=url&iiurlwidth=1280&format=json"
Arthur Ashe Stadium 01.JPG 썸 URL이 1280px 규격으로 나왔고, HTTP 200을 확인한 뒤 채택했다. IT 글 자체는 “검색 엔진” 메타포에 맞춰 Commons Magnifying-glass.svg PNG 렌더를 썼다. 헬스케어 Talkspace 글은 Openverse에서 telemedicine+doctor+video로 의사·스마트폰 목업을 골랐고, 미디어 Onslaught 리뷰는 Commons Landmark's Atlantic Plumbing Cinema screening_room.jpg로 극장 상영 맥락을 맞췄다.
이유: 한 소스만 쓰면 왜 깨지나
Openverse는 Flickr·Wikimedia 등을 집계하므로 키워드가 넓으면 인기 태그가 상위를 차지한다. review가 들어간 무관한 사진, 연예인 컷, 과거 대회 사진이 섞인다. Commons는 파일명·카테고리가 명확한 반면, PDF 썸네일·오디오 아이콘이 검색 상위에 끼어 들어온다(이번 Cinema projector 검색이 그랬다). 그래서 기준 문서가 “두 소스 이상”을 요구하는 것이다. 라이선스는 cc0,pdm,by,by-sa만 통과시키고 mature=false는 Openverse에서 필수 파라미터로 고정했다.
적합도 100% 체크는 자동화하기 어렵지만, 최소한 아래는 사람·에이전트가 문장으로 적어야 한다.
| 글 주제 | 탈락한 후보 | 채택한 시각 주제 |
|---|---|---|
| 조코비치 US오픈 1R | 세리나 윌리엄스 경기 컷 | 아서 애시 스타디움 전경 |
| Onslaught 리뷰 | 좀비 스톡 사진(다른 작품) | 극장 스크리닝 룸 |
| 부동산 세제 한 달 | (없음) | 서울 아파트 단지 외관 |
평가: cron에 넣을 최소 절차
이 레포 자동화에는 아래 순서를 고정하는 편이 낫다.
- 제목에서 시각 주제 한 문장 작성(예: “병원·가상 진료 앱 → 의사+스마트폰, 연예인 제외”).
- Openverse 1회 + Commons
generator=search1회 이상. - 후보마다
curl -sI로 200·가로 ≥600px 확인. - 라이선스·SFW·금지 인물 목록 통과분만
heroImage/heroAlt에 기록. npm run build전 frontmatter 검증.
heroAlt에는 주제·작품명·라이선스·소스를 한 줄로 넣었다. CC BY는 출처 절에 Flickr 사용자명을 추가할 수 있다. 적합도가 95%면 탈락이 규칙이므로, “대충 스포츠 사진”은 넣지 않는다.
부연: 어디에 안 쓰는지
이 워크플로는 브랜드 로고·OG 기본 이미지(og-default.jpg) 교체용이 아니다. public/images/는 로고·파비콘만 유지한다. 뉴스 기사 핫링크·Google CDN 썸네일도 여전히 금지다. API가 401·타임OUT이면 WebSearch로 URL을 추측 생성하지 말고 해당 글 발행을 중단한다(A.2).
다음 배치에서는 Openverse source=wikimedia 필터를 추가해 중복을 줄이고, Commons 쪽은 filetype:bitmap에 가까운 파일명만 고르는 스크립트를 검토 중이다. 지금도 수동 curl 두세 번이면 7편 히어로를 30분 안에 걸러낼 수 있었다. 비용은 API 호출 수준이고, 잘못된 정치인 컷 한 장을 막는 효과는 훨씬 크다.
출처
- 내부 실측: 2026-09-01 cron VM에서 Openverse
api.openverse.org/v1/images/및 Commons MediaWiki API 호출·HTTP 200 확인 - Notion 시드: «디버깅» — Graft·색인 워크플로 맥락(히어로 절차와 별개, 공개 가능 요지만)
- Openverse API documentation —
license,mature파라미터 (열람: 2026-09-01) - Wikimedia Commons API —
generator=search+imageinfo패턴 (열람: 2026-09-01)