3 min read · 758 words
#243
이 글은 다국어 블로그 인프라를 운영하며 인덱싱 불일치로 골머리를 앓는 개발자와 시스템 관리자를 위한 운영 가이드다. 자동화된 발행 체인에서 언어별 라벨이 의도와 다르게 꼬여 사용자 경험과 검색 엔진 최적화(SEO)에 치명적인 악영향을 주는 문제를 해결한 과정을 공유한다.
문제 상황
운영 기록 기준, 사장님이 라이브 상태인 /search/label/AI%20Deep%20Dive (영어 라벨) 페이지를 모니터링하던 중 한국어, 일본어, 중국어, 스페인어 글이 무작위로 섞여 노출되는 현상을 발견했다. blogger 플랫폼 기반으로 5개 언어(KO, EN, JA, ZH, ES)를 타깃하여 각 언어별 전용 라벨 색인 페이지를 제공하고 있었기에, 이는 서비스 기획 의도를 정면으로 위배하는 상황이었다. 나는 즉시 전체 발행 본문에 대한 5 lang label 색인 정합성 검증 작업에 착수했다. 전체 라이브 포스트를 대상으로 매트릭스 스캔을 돌려본 결과, 영어(EN) 라벨이 지정된 29편의 포스트 중 무려 11편이 영어가 아닌 다른 언어의 글(일본어 4편, 중국어 2편, 스페인어 4편, 한국어 1편)로 채워져 있었다. 반면 스페인어(ES) 라벨 7편 중 1편은 영어 글이었고, 한국어(KO), 일본어(JA), 중국어(ZH) 라벨 페이지는 정확하게 작동하고 있었다. 즉, 시스템 내에서 EN 라벨이 매칭 오류 시 모든 글을 흡수하는 catch-all fallback으로 잘못 동작하여 다국어 글의 일부가 EN 라벨로 떨어지는 현상이 발생하고 있었다.
에러 증상
이 오류로 인해 blogger 내부 인덱싱 구조와 외부 SEO 지표 모두에 심각한 에러 증상이 나타났다. 첫째, 사용자가 영어 기술 아티클을 읽기 위해 'AI Deep Dive' 라벨 페이지에 진입했을 때 느닷없이 일본어나 중국어로 작성된 본문이 노출되어 5 lang 분류 체계에 대한 신뢰도가 완전히 깨졌다. 둘째, 검색 엔진의 크롤러(SEO crawler) 관점에서 특정 언어 라벨 페이지의 HTML 메타태그 정보와 실제 렌더링되는 본문의 언어가 일치하지 않아 언어 일관성(Language Consistency) 신호가 부정확하게 전달되었다. 이는 도메인 전체의 SEO 랭킹 점수를 갉아먹는 치명적인 원인이 되었다. 에러가 발생해도 발행 프로세스 자체는 정상 종료(200 OK)로 기록되었기 때문에, 모니터링 시스템에서 잡아내지 못하고 백그라운드에서 조용히 데이터가 오염되는 'Silent Swap' 사고의 전형적인 모습을 보여주었다.
환경
내부 테스트 기준 및 현재 프로독션 인프라는 Python 기반의 FastAPI 백엔드를 주축으로 구동된다. blogger 백엔드 API와 통신하며 포스트를 제어하는 핵심 모듈은 blogger.py 파일 내에 구현된 publish chain이다. 포스트 발행 시 내부 정제 규칙에 따라 라벨을 제어하는 _canonical_toolsignal_label 함수와, 최종 발행 직전 규칙을 강제하여 최종 라벨 배열을 반환하는 _enforce_toolsignal_labels 함수가 핵심 파이프라인을 구성하고 있다. 자동 발행 호출부(caller)로는 tip_auto_publisher 모듈의 publish_draft_via_webapp 함수가 연동되어 초안을 라이브 포스트로 전환하는 역할을 담당한다.
시도했지만 실패한 방법
정확한 원인은 추가 확인이 필요하지만, 현재 확인된 직접적인 원인은 레거시 스키마 전환 과정에서의 설계 미스였다. 과거에 사용하던 'AI 파헤치기/뉴스/활용 팁/리뷰/다국어' 체제의 5-canon 구조에서, 최근 sess143 업데이트를 통해 새로운 5 lang single-topic schema로 스왑을 단행했다. 이 과정에서 과거의 '다국어' 라벨이 매핑될 때 조건이 맞지 않으면 무조건 EN 라벨로 떨어지도록 fallback이 설계된 것이 화근이었다.
내가 처음에 문제를 해결하기 위해 시도했던 방법은 단순 script 기반 detect 로직을 적용하는 것이었다. 그러나 title이나 content의 실제 언어를 정밀하게 디텍팅하지 않고, 이미 지정된 label 자체의 텍스트만 보고 swap을 시도하는 바람에 실패했다. 이미 'AI Deep Dive'라는 영어 텍스트 라벨이 박혀 들어온 ja/zh/es 포스트는 라벨 이름 자체가 영어 정보이기 때문에 script 기반 detect 로직을 그대로 통과해 버렸다. 또한, 기존 _canonical_toolsignal_label 함수를 고쳐보려 했으나, 상위 호출부인 tip_auto_publisher에서 정확한 language hint를 인자로 넘겨주지 않고 있었기 때문에 hint 값이 없는 상태에서는 여전히 똑같은 fallback 오류가 재발했다. 호출부의 신뢰성이 확보되지 않은 상태에서 하위 필터만 수정하려 했던 시도는 실패로 돌아갔다.
최종 해결
문제를 근본적으로 해결하기 위해 나는 blogger.py 내부의 최종 관문인 _enforce_toolsignal_labels(labels, title, content, language) 함수를 전면 개편했다. 상위 caller가 넘겨주는 부실한 language hint에만 의존하지 않고, 들어오는 title 문자열의 유니코드 script 구역을 직접 분석하여 강제로 언어 라벨을 스왑하는 로직을 삽입했다. 가나(일본어), 한글(한국어), 한자(중국어), 역물음표나 악센트 기호 등의 스페인어 특수문자를 정규식 및 유니코드 범위로 분석하여 정확한 언어를 판별하도록 했다. 이 유니코드 script 기반 분석 결과가 나오면 기존에 잘못 지정된 EN 라벨을 무시하고 정확한 언어 라벨로 강제 swap 처리를 수행한다. 호출부가 제공하는 language hint는 오직 유니코드 분석 결과가 모호할 때만 사용하는 2차 fallback으로 격하시켰다. 이후 시스템을 배포하고, 이미 오염된 라이브 데이터 12편(EN 매치스왑 11편, ES 매치스왑 1편)에 대해 Blogger API의 posts.patch 메서드를 호출하여 올바른 labels 데이터로 매뉴얼 스왑을 적용하여 DB와 라이브 페이지를 동기화했다.
사용한 코드
다음은 blogger.py 내에 수정 적용한 실제 파이프라인 강제 스왑 코드의 일부다.
/app/backend/publisher/blogger.py
[이전 코드]
def _enforce_toolsignal_labels(labels, title, content, language=None): # caller의 hint가 없거나 부정확하면 기본적으로 영어 single-topic으로 fallback 처리됨 if not language or language ==