피드가 빨라지더니 시끄러워졌습니다
지난 2월에 파이프라인을 쪼개다라는 글을 썼습니다. 당시 운영하던 AI 뉴스 피드는 하루 세 번만 돌아서 업데이트 사이사이에 화면이 멈춰 있는 것처럼 보였습니다. 그래서 30분마다 스냅샷을 찍는 Tier-1과 하루 세 번 전체 랭킹을 돌리는 Tier-0으로 파이프라인을 나눴고 API에서 두 결과를 합쳐 새 글이 상단에 바로 올라오게 했습니다.
그때 급했던 건 속도였습니다.
그런데 10월쯤 되자 아침에 사이트를 열 때마다 절반 가까운 카드를 그냥 넘기고 있었습니다. 어느 날은 Google News 검색 쿼리 하나에서 나온 DeepSeek V4.1-Flash 출시 기사가 한 화면에 일곱 장이나 깔렸습니다. 제목과 매체만 달랐습니다. Anthropic의 “2026 Usage Policy update” 공지가 며칠 내내 상위권을 지키는 동안 정작 엔지니어링 블로그 글은 거의 보이지 않았고 본문이 사진 캡션 한 줄뿐인 검색 기사가 올라온 날도 있었습니다.
기분 탓인가 싶어서 8일치 빌드 201개를 전부 뽑아봤습니다. 전체 슬롯은 4,824개였는데 고유 URL은 382개뿐이었습니다. 직전 빌드와 겹치는 항목이 87%에 달했고 48시간이 지난 글도 21%나 됐습니다. 8일 동안 Anthropic 이용 정책 공지는 88번이나 노출됐습니다. 같은 기간 엔지니어링 블로그가 받은 자리는 13번뿐이었는데 그마저도 글 하나가 계속 반복된 결과였습니다.
경로가 둘이면 기준도 둘이 됩니다
2월에 그렸던 다이어그램은 역할이 깔끔해 보였습니다.
그림 1. Tier-1은 API로 바로 들어가면서 동시에 Tier-0의 입력이 됐습니다. 독자 화면에는 서로 다른 두 필터를 통과한 글이 뒤섞여 올라왔습니다.
막상 몇 달을 돌려보니 두 레인은 “좋은 글”의 기준부터 달랐습니다. Tier-1은 새 링크를 몇 분 안에 올리려고 최신성과 소스 가중치, 간단한 키워드 몇 개만으로 점수를 매겼고 Tier-0은 몇 시간 뒤에야 전체 랭킹을 돌렸습니다. API가 요청 시점에 두 스냅샷을 합치다 보니 정식 랭킹이 걸러내기도 전에 검색 결과가 맨 위 자리를 먼저 차지하곤 했습니다.
검색 피드는 문제를 더 키웠습니다. 출시 소식을 빨리 잡으려고 넣었는데 Google News 검색 결과가 직접 고른 엔지니어링 블로그와 같은 풀에서 경쟁하게 된 것입니다. 기업 블로그에는 높은 신뢰도 가중치가 붙어 있어서 주요 AI 랩의 정책 공지나 홍보 글이 며칠씩 상단에 머물렀습니다. 게다가 랭킹에는 기억이 없었습니다. 매번 백지에서 다시 계산하느라 이번 주에 이미 몇 번이나 보여준 링크인지도 몰랐습니다.
모델을 붙이기 전에 규칙으로 거를 수 있는 것부터 걷어냈습니다
LLM을 부르기 전에 코드로 잡을 수 있는 중복부터 정리했습니다.
우선 모든 소스를 공식 랩 블로그, 실무자, 어그리게이터, 커뮤니티, 검색, 릴리스, 연구의 일곱 가지 역할로 분류했습니다. 공식 랩 블로그는 엔지니어링과 뉴스룸으로 쪼개서 뉴스룸 공지는 최대 한 자리만 주도록 묶었습니다. Anthropic 최소 보장 슬롯도 엔지니어링 글만 세도록 바꿨습니다. 검색 결과나 기업 홍보 글은 제목에 구체적인 출시나 기술 신호가 없으면 격리했고 같은 사건을 다룬 기사는 하나로 합쳤습니다. 직전 회차에 이미 노출된 이야기에는 반복될수록 커지는 감점을 매겼습니다.
효과는 바로 나타났습니다. 출시 하나가 카드 일곱 장을 도배하던 일은 그날로 사라졌습니다.
대신 규칙만으로는 안 되는 영역이 또렷해졌습니다. 정규식이나 키워드 규칙은 “Claude Code vs Codex” 같은 단순 비교 글이나 IPO 루머는 잘 잡아냅니다. 하지만 글 안에 실제 엔지니어링 내용이 담겨 있는지는 읽지 못합니다. 검색에서 건진 진짜 단독 기사와 조회수용 요약 글을 가려내거나 에이전트 연동 방식을 바꾸는 발표와 평범한 고객 도입 사례를 구분하는 일도 규칙으로는 버겁습니다. 에이전트 평가 논문과 제목에 우연히 “eval”이 들어간 임상 의학 벤치마크를 가려내는 일도 마찬가지입니다.
가중치나 차단 목록을 더 만져봐야 오류의 위치만 바뀔 뿐이었습니다. 본문을 읽고 “이 글이 플랫폼 엔지니어의 시간을 쓸 만한가?”에 답해줄 평가 모델이 필요했습니다.
애매한 글 50개로 벤치마크를 만들었습니다
프로덕션 파이프라인을 고치기 전에 골치 아팠던 여덟 가지 유형에서 글 50개를 골랐습니다. 기업 엔지니어링 블로그, 기업 마케팅, 실무자 분석, 검색 유입용 SEO 글, 업계 가십, 분야가 다른 과학 기사, 연구 논문, 릴리스 노트가 고루 들어가 있습니다. 항목마다 제목과 출처, 2,500자 분량의 본문 발췌를 넣고 통과·탈락 여부와 함께 “꼭 읽어야 할 글”부터 “잡음”까지 네 단계 등급을 매겼습니다.
규칙이 번번이 속았던 경계선 사례도 일부러 섞었습니다. 통과시켜야 하는 쪽에는 에이전트 상호운용성을 바꾸는 기업 발표와 진짜 검색 단독 기사, 출시 당일 올라온 서빙 경험담을 넣었고 걸러내야 하는 쪽에는 기술 블로그 문체로 쓴 투자 유치 기사와 임상 질의응답 벤치마크, 도구 비교 글을 넣었습니다. 라벨은 코딩 에이전트의 도움을 받아 제가 직접 붙였습니다. 아직 잠정적인 기준입니다. 50개면 좋은 모델을 최종 증명하기엔 부족해도 망가진 기준을 잡아내기에는 충분합니다.
평가 모델로는 OpenRouter에서 제공하는 TypeSafe의 Jev를 썼습니다. 줄글로 판정 이유를 생성하지 않는 모델입니다. 정해진 형식의 질문 목록을 보내면 예/아니오 질문에는 확률값을 돌려주고 객관식 질문에는 선택지별 분포를 돌려줍니다. 응답 문장을 다시 파싱할 필요가 없어서 파이프라인 중간에 넣기 좋았습니다.
같은 50개 세트로 세 가지 구성을 비교해 봤습니다.
| 지표 | 질문 넷 + 분류 | 질문 하나 | 규칙 기반 기준선 |
|---|---|---|---|
| AUC | 0.969 | 0.965 | 0.871 |
| 최적 임계값 F1 | 0.927 | 0.878 | 0.829 |
| 정밀도 | 0.950 | 0.900 | 0.850 |
| 재현율 | 0.905 | 0.857 | 0.809 |
요청 50개에 든 비용은 0.0027달러였고 건당 응답 시간은 평균 440ms 정도였습니다.
질문 하나에 서로 다른 기준 네 개가 섞여 있었습니다
“이 글이 오늘 브리프에 들어갈 만한가?”라는 질문 하나만 던져도 규칙 기반보다 F1이 5포인트 가까이 높았습니다. 다만 틀리는 방식이 일정했습니다.
- 학습 데이터가 적은 소수 언어를 다룬 논문을 방법론이 탄탄하다는 이유로 통과시켰습니다. 논문 자체는 훌륭하지만 플랫폼 엔지니어링 피드가 다룰 주제는 아닙니다.
- 본문에 실제 서비스 사용량 숫자가 인용돼 있다는 이유로 투자 유치 기사를 통과시켰습니다.
- “OpenAI models are coming to Google Cloud” 기사에는 0.12점을 줘서 탈락시켰습니다. 문투가 흔한 제휴 보도자료 같았기 때문인데 실제로는 모델을 배포하고 호출하는 클라우드 환경이 바뀌는 소식이었습니다.
점수 하나에 네 가지 판단이 한꺼번에 구겨 넣어진 셈이었습니다. 그래서 질문을 넷으로 쪼갰습니다. 브리프에 실을 만한 글인가, AI 시스템을 만들고 운영하는 이야기인가, 단순 버전 업데이트나 일상적인 릴리스 노트인가, 구체적인 기술 변화가 없는 기업 홍보성 소식인가를 따로 묻습니다. 여기에 뒤쪽 편집 단계에서 쓸 주제를 고르는 객관식 질문 하나를 더했습니다.
네 확률을 그냥 곱해봤더니 F1이 0.810으로 오히려 떨어졌습니다. 대신 “브리프에 실을 만한가”를 기본 점수로 두고 나머지 세 답을 상한선으로 쓰는 방식이 잘 맞았습니다. 일상적인 릴리스 노트나 기업 홍보 신호가 높게 나오거나 플랫폼 관련성이 낮으면 기본 점수를 바닥으로 눌러버리는 식입니다. 이렇게 바꾸자 F1이 0.927까지 올라갔습니다.
점수 미달을 바로 버렸더니 피드가 비었습니다
정밀도가 0.95까지 나오는 것을 보고 처음에는 단순한 커트라인 필터로 붙였습니다. 가벼운 1차 규칙으로 하루 후보를 140개 정도로 줄인 뒤 평가 모델이 탈락으로 판정한 글을 전부 버리는 방식입니다.
결과는 오히려 더 나빠졌습니다.
후보의 60%가량이 한꺼번에 잘려 나가면서 에이전트 도구 릴리스처럼 원래 모수가 적은 섹션은 아예 0개가 됐습니다. 그런데 랭킹 단계에는 섹션별 최소 할당량과 전체 피드 개수를 채우라는 규칙이 남아 있었습니다. 결국 랭킹이 빈자리를 메우려고 탈락한 더미에서 점수가 덜 낮은 글을 다시 끌어왔고 중복은 줄어든 대신 알맹이 없는 글이 늘어났습니다.
글을 한 편씩 따로 채점하는 모델은 오늘 후보 풀에 좋은 엔지니어링 글이 세 편뿐인지 서른 편인지 알 길이 없습니다. 이번 회차에 릴리스 노트나 커뮤니티 글이 이미 몇 개나 들어갔는지도 모릅니다. 전체 구성을 맞추는 일은 랭킹의 몫입니다.
그래서 커트라인 필터를 껐습니다. 대신 평가 점수를 랭킹의 가중치 중 하나로 넘겼습니다. 점수가 높으면 정해진 상한 안에서 가산점을 받고 점수가 낮으면 감점을 받아 여유 슬롯에 들어가지 못합니다. 읽을 만한 새 글이 적은 날에는 억지로 채우지 않고 피드가 일찍 끝납니다.
두 층으로 나눴던 파이프라인을 하나로 합쳤습니다
한 번 돌리는 데 1센트도 들지 않는 판별 단계가 생기자 평가를 건너뛰는 빠른 계층을 따로 둘 이유가 사라졌습니다. Tier-1 빌드 코드와 213MB 분량의 스냅샷을 지웠습니다. 이제 API는 최종 발행본 하나만 읽습니다.
그림 2. 사전 규칙으로 중복과 홍보 글을 먼저 정리한 뒤 후보 약 140개를 Jev로 평가합니다. 이전 판정을 재사용하고 점수는 랭킹에 가중치로 넘깁니다.
파이프라인은 두 시간마다 한 경로로만 돕니다. 소스를 수집하고 사전 규칙으로 후보를 140개 남짓으로 추린 뒤 Jev로 평가하고 랭킹을 매겨 발행합니다. 실제 운영 환경에 올렸을 때 품질을 가른 것은 세부 동작 세 가지였습니다.
요약이 짧으면 본문을 직접 가져옵니다
첫 라이브 테스트에서 Cloudflare가 올린 추론 비용 분석 글이 뜻밖에 낮은 점수를 받았습니다. 원인은 입력 텍스트였습니다. 모델에 넘긴 발췌문이 본문이 아니라 상단 내비게이션 메뉴였던 것입니다. 벤치마크를 만들 때는 본문 2,500자를 넣어줬는데 실제 RSS 피드에서는 한 줄짜리 요약만 넘어오는 경우가 많았습니다. 지금은 피드 요약이 너무 짧으면 원문 페이지에서 본문을 최대 2,500자까지 가져온 뒤에 평가 모델을 호출합니다.
한 번 내린 판정은 저장소에 기록합니다
새 머신에서 도는 CI 빌드에서는 로컬 캐시가 남지 않습니다. 같은 글을 두 시간마다 다시 채점하지 않으려고 판정 기록을 데이터 파일과 함께 저장소에 커밋해 두었습니다. 글의 식별자와 모델 버전, 질문 문구, 프롬프트를 묶어 키를 만들고 14일 동안 보관합니다. 이 가운데 하나라도 바뀌면 그때 다시 평가합니다.
캐시가 비어 있던 첫 실행에서는 후보 140개를 전부 평가했습니다. 통과 93개, 탈락 31개, 검토 16개로 나뉘었고 최종 피드에는 22개가 올라갔습니다. 다음 빌드에서는 138건을 기존 기록에서 그대로 가져왔고 새로 호출한 것은 2건뿐이었습니다.
릴리스 노트는 메인 브리프와 분리합니다
일상적인 버전 업데이트나 릴리스 노트는 감점 규칙에서 예외로 두었습니다. 자잘한 패치 노트가 메인 브리프 화면에서는 빠지더라도 릴리스 전용 탭에는 그대로 올라옵니다.
요약·위키 페이지도 같은 평가 결과를 씁니다
사이트의 데일리 요약, 위클리 요약, 플레이북, 위키, 파운데이션 페이지는 에디터 에이전트가 작성합니다. 이제 에이전트도 글마다 Jev가 매긴 점수와 주제 분류를 함께 받아 보고 이미 탈락 판정을 받은 글은 건너뜁니다.
처음에는 평가 모델이 추려낸 후보 140개 풀을 에디터 에이전트에 바로 넘기려 했습니다. 실제 데이터를 열어보고 접었습니다. 그 풀은 두 시간짜리 단일 실행 결과만 담고 있는 데다 본문 텍스트가 없고 연구 논문 비중이 지나치게 높았습니다. 후보 140개 중 100개가 arXiv 논문이었던 회차도 있었습니다. 그래서 에디터 덱은 기존처럼 완성된 발행본을 읽되 거기에 평가 결과와 주제 라벨만 덧붙여 받습니다. 예전에 애매한 글을 다 몰아넣던 “Industry News” 분류는 Jev가 고른 세부 주제로 대체했고 위키와 파운데이션 페이지에서는 일상적인 릴리스 노트를 자동으로 뺍니다.
외부 API 장애로 평가 모델을 호출하지 못하거나 아직 점수가 없는 항목이 섞여 들어와도 피드와 에디터 덱은 멈추지 않고 기존 규칙만으로 동작을 이어갑니다.
이 개편이 남긴 것
2월에 파이프라인을 두 층으로 쪼갰을 때는 업데이트 지연이라는 눈앞의 문제를 풀었습니다. 여덟 달이 지나고 보니 경로가 둘이라는 사실 자체가 서로 다른 두 편집 기준을 만들고 있었습니다. 이제 첫 화면에 올라오는 모든 카드는 같은 기준을 통과해야 하고 읽을 만한 글이 적은 날에는 억지로 24개를 채우는 대신 18개에서 조용히 끝납니다.