Joyuno's Dev Blog

2026-08-06 (목) 개발일지

dev-blog

오늘은 두 갈래 작업이었다. 하나는 옵시디언 정리 과정에서 기존 arxiv 논문 주간 파이프라인을 GeekNews Weekly 최신호 요약으로 갈아엎은 일, 다른 하나는 사주 앱의 앱인토스 출시 전략에서 채팅 기능이 가이드 위반인지를 검증한 일. 둘 다 첫 번째 가설이 중간에 뒤집혔고, 그 전환점에서 실제 원인과 제약을 잡았다.

GeekNews Weekly 파이프라인 — arxiv 논문 대신 원문 35건 요약으로 전환

이번 주 발행물이 사이트에서 보이지 않는다는 얘기가 들어왔다. 처음엔 기존 arxiv 논문 워크플로(weekly-papers.yml)가 아직 백그라운드에 남아 새 발행을 밀어낸 것이라 생각했다. 그래서 제일 먼저 옛 워크플로를 취소했다. 그런데 취소하고 나니 “무엇으로 대체할지”가 정의되지 않았다는 게 진짜 문제였다.

GeekNews Weekly 페이지 구조를 조사했다. 최신호는 /weekly/202631(YYYYWW = 2026년 31주차)이었고, 각 “주요 뉴스” 항목이 news.hada.io/topic?id=31899 형태의 원문 링크로 연결됐다. 결정적인 발견은 여기서 나왔다.

GeekNews는 /topic/{id}.md라는 깨끗한 마크다운 엔드포인트를 제공하고 있어서, HTML 파싱 없이 그대로 fetch해서 요약 소스로 쓸 수 있었다.

수집기는 geeknews_weekly_collector.py, 요약은 weekly_news_summarizer.py에서 deepseek/deepseek-v4-flash로, 발행은 weekly_news_publisher.py가 담당하는 3단 구성으로 파이프라인을 완성했다. 도중에 병렬 포크가 이미 수집기를 만들어둔 상태라는 것도 발견했다. 클로버 방지를 위해 파이프라인 전체 상태를 먼저 진단하고, 중복 없이 내 쪽 모듈만 합치는 방향으로 정리했다. 첫 dry-run에서 톤·포맷·매체명 미언급 규칙은 통과했지만, 토큰 상한으로 일부 항목이 잘린 게 다음 사건의 시작이었다.

요약 5줄 잘림 — deepseek-v4의 reasoning 토큰이 max_tokens를 잠식

링크 footer와 구분선을 추가하고 커밋·푸시한 뒤 force 재발행을 돌렸다. 결과물을 보니 요약이 문장 중간에서 끊겨 있었다. 항목 1은 2줄, 항목 3은 4줄에서 잘렸다. 처음엔 가독성 개선 커밋이 뭔가를 깨뜨렸다고 의심했다. 하지만 그 커밋은 마크다운 템플릿(weekly_news_post.j2)과 footer만 건드렸고, 요약 생성 로직은 손도 대지 않았다.

dry-run으로 재검증하자 실제 잘림이 재현됐다. 전부 문장 중간에서 끊겼고, “요약이 잘된 게 아니라” 애초에 출력이 완결되지 않았다. 원인은 weekly_news_summarizer.py의 MAX_OUTPUT_TOKENS였다.

deepseek-v4는 reasoning 토큰이 max_tokens를 함께 먹는 구조라서, 답변 생성 전에 이미 상한을 소진했다.

arxiv 논문 요약기(paper_digest_summarizer.py)는 2200이라 정상이었는데, GeekNews 쪽은 700으로 잡혀 있었다. 700 → 2000으로 올리고 dry-run을 다시 돌렸다. 35건 전부 5줄이 온전히 나오는 걸 확인한 뒤에야 실발행을 트리거했다.

항목 before after
MAX_OUTPUT_TOKENS 700 2000
문장 중간 잘림 2건 이상 0건
5줄 완결성 항목 1: 2줄, 항목 3: 4줄 35/35

검증: 라이브 발행 글(/blog/2026/08/03/tech-weekly/)에서 링크 footer 35/35(GitHub 20 · 원문 25), 항목 간 구분선 반영, 잘림 0건을 확인했다. fetch 실패 시 weekly 페이지의 짧은 인라인 요약으로 fallback하는 로직은 아직 스트레스 테스트를 못 돌려본 게 남은 과제다.

앱인토스 — “채팅은 위반”이라는 전제가 틀린 이유

사주 앱에 “궁합이 잘 맞는 사람과 소개팅까지 주선” 기능을 앱인토스로 내는 작업이었다. 출시 전략의 핵심 쟁점은 채팅 기능이 가이드 위반인지였다. 처음엔 만남·소개팅 카테고리가 가이드에 없을 거라 보고, 채팅을 빼거나 극도로 제한해야 한다고 생각했다.

공식 가이드를 직접 조회하면서 첫 번째 전제가 깨졌다. 앱인토스는 Flutter를 지원하지 않았다. WebView SDK 또는 React Native SDK(공통 런타임 Granite)만 지원하는 구조였고, 이게 “현재 레포에서 뭘 재사용할지”를 결정적으로 바꿨다. Flutter 프론트는 재사용 불가, 백엔드·로직·디자인만 가져갈 수 있었다.

두 번째로 깨진 전제는 채팅이었다. 가이드를 보니 “만남·소개팅”은 조건부 허용이었다. **성인