오늘 하루 동안 다섯 개 문제가 연쇄적으로 터졌다. 하나 고치면 다음 문제가 나왔다. 그 과정을 순서대로 기록한다.
문제 1: 뉴스가 한 달 전 기사였다
Whalyx 메인 페이지에 글로벌 경제 뉴스를 붙이려고 NewsAPI를 썼다. 근데 뉴스가 이상했다. 최신 헤드라인이 4월인데 3월 기사가 올라왔다.
알고 보니 NewsAPI 무료 티어는 최근 1개월 이전 기사만 제공한다. 돈을 내야 실시간이다.
해결책은 Google News RSS였다. API 키 없이 feedparser로 긁어오면 실시간 헤드라인이 들어온다.
import feedparser
feed = feedparser.parse("https://news.google.com/rss/search?q=stock+market&hl=en-US&gl=US&ceid=US:en")
headlines = [entry.title for entry in feed.entries[:20]]
무료, 실시간, API 키 없음. 교체하는 데 30분 걸렸다.
문제 2: 뉴스를 그냥 나열하면 의미가 없다
20개 헤드라인을 리스트로 보여주는 건 사용자한테 짐을 떠넘기는 거다. "이게 오늘 시장에 어떤 영향을 주는지" 해석해줘야 한다.
그래서 Gemini를 넣었다. 20개 헤드라인을 통째로 보내고 이렇게 물어봤다.
오늘 시장에 가장 큰 영향을 줄 뉴스 3개를 골라줘.
각각 bullish / bearish / mixed 판단과 한국어 요약, 영향 설명을 JSON으로 반환해.
반환 결과가 이런 구조다.
[
{
"title": "Fed signals rate cut delay",
"sentiment": "bearish",
"summary": "연준, 금리 인하 시기 재검토",
"impact": "성장주 전반에 하락 압력"
}
]
이걸 메인 페이지 추천 종목 위에 3개 카드로 표시했다. 사용자가 앱 열자마자 오늘 시장 분위기를 3초 안에 파악할 수 있게 됐다.
문제 3: Gemini SDK가 오류를 폭발시켰다
Gemini를 붙이는 과정에서 400 오류가 계속 났다. 원인을 파보니 SDK 버전 문제였다.
기존에 쓰던 google-generativeai는 deprecated된 구버전이었다. gemini-2.5-flash와 충돌해서 400이 떴다. 더 심각한 건 재시도 로직이었다. 400이 뜨면 재시도를 반복하는 코드가 있었는데, 이게 429 오류를 40개 찍어냈다. 하루 할당량을 몇 분 만에 다 썼다.
해결은 두 가지였다.
첫째, SDK를 google-genai 신규 버전으로 교체했다.
# Before (deprecated)
import google.generativeai as genai
# After
from google import genai
client = genai.Client(api_key=settings.GEMINI_API_KEY)
둘째, 재시도를 1회로 제한하고 타임아웃을 25초로 박았다. 오류가 나도 더 이상 폭주하지 않는다.
문제 4: Railway가 유료로 전환됐다
백엔드를 Railway에 올려뒀는데 Trial 기간이 끝났다. 계속 쓰려면 월 사용료가 나간다. 사이드 프로젝트에 고정비를 붙이긴 싫었다.
Render Free Tier로 이전했다. 무료지만 두 가지 문제가 있었다.
첫 번째는 슬립이다. 15분 이상 요청이 없으면 서버가 잠들고, 다음 요청 시 30초~1분 걸려 깨어난다. UptimeRobot으로 5분마다 핑을 날려서 해결했다.
두 번째는 타임아웃이다. Render Free Tier는 요청 타임아웃이 30초다. Gemini API 호출이 길어지면 그냥 끊긴다. 앞에서 Gemini 타임아웃을 25초로 맞춰둔 게 여기서 맞아떨어졌다. Render가 끊기기 전에 Gemini가 먼저 정리하고 응답을 반환한다.
문제 5: 서버 재시작마다 Gemini를 다시 호출했다
Render는 배포할 때마다 서버가 재시작된다. 메모리 캐시가 전부 날아간다. Gemini 뉴스 분석 결과도 마찬가지였다. 재시작할 때마다 Gemini를 새로 호출하니 할당량이 계속 깎였다.
Supabase DB에 캐시를 저장하도록 바꿨다. TTL은 30분.
async def get_cached_news(db):
cached = await db.execute(
select(NewsCache).where(
NewsCache.created_at > datetime.utcnow() - timedelta(minutes=30)
)
)
return cached.scalar_one_or_none()
서버가 재시작돼도 DB에 30분 이내 캐시가 있으면 그걸 쓴다. Gemini 호출이 대폭 줄었다.
오늘 변경 요약
항목 Before After
| 뉴스 소스 | NewsAPI (1달 전 기사) | Google News RSS (실시간) |
| 뉴스 표시 | 20개 리스트 나열 | Gemini 선별 3개 카드 |
| Gemini SDK | google-generativeai (deprecated) | google-genai (신규) |
| 배포 플랫폼 | Railway | Render Free Tier |
| 뉴스 캐시 | 메모리 (재시작 시 소멸) | Supabase DB (30분 TTL) |
마무리 — 문제는 항상 연쇄적으로 온다
오늘 작업을 돌아보면 각각의 문제가 독립적이지 않았다. Gemini를 붙이니 SDK 문제가 터졌고, SDK 고치니 재시도 로직 문제가 나왔고, Railway를 바꾸니 타임아웃 문제가 생겼고, 타임아웃 맞추니 캐시 소멸 문제가 드러났다.
사이드 프로젝트에서 이런 날이 가장 배우는 게 많다. 하나씩 막다 보면 전체 흐름이 보인다.
Whalyx는 계속 만드는 중이다.
'AI 엔지니어준비' 카테고리의 다른 글
| Claude Code, 제대로 세팅하면 AI가 팀이 된다 (0) | 2026.04.07 |
|---|---|
| "신뢰감이 없어 보인다" — 피드백 하나로 Whalyx를 하루 만에 뜯어고쳤다 (0) | 2026.03.26 |
| Claude 3명이 팀 개발했더니 하루 만에 앱이 배포됐다 (0) | 2026.03.25 |
| 코드 한 줄 안 쓰고 실제 카페에 투입한 재고관리 앱을 하루 만에 만든 방법 (0) | 2026.03.24 |
| 자주 사용하는 Python 패턴 (0) | 2026.02.19 |