목차
- 오늘 한 것 — Claude API status + 헤드라인을 같은 축에
- 새로 알게 된 것 — 헤드라인과 가용성은 거의 무관하다
- 코드 — 헤드라인과 status를 같이 보는 작은 대시보드
- 메모 — 다음에 해볼 것
오늘 한 것 — Claude API status + 헤드라인을 같은 축에
PR 자동 리뷰 봇을 운영 중이다. GitHub Actions에서 PR이 열리면 diff를 잘라 Claude Sonnet에 넘기고, 보안 이슈와 컨벤션 위반만 추려서 슬랙 채널에 푸시한다. 일주일에 평균 40~60건 정도 돈다. 이게 멈추면 코드 리뷰가 사람 손으로 되돌아가야 한다. 그래서 외부 의존성 하나는 늘 신경 쓰고 있다 — Anthropic API.
한 달 전쯤 status.anthropic.com 폴링 스크립트를 띄워뒀다. JSON 엔드포인트가 친절하게 열려 있어서 별것 안 만들어도 된다. 60초마다 fetch해서 incidents 배열이 비었는지 확인하고, 비지 않으면 PagerDuty로 알림 가게 해뒀다.
원래는 거기서 끝이었다. 이번 주에 한 줄 더 붙였을 뿐이다. Google News RSS에서 "Anthropic" 키워드 헤드라인을 같은 주기로 수집해서 같은 SQLite에 박아두는 것. 이유는 단순했다. 최근 며칠 동안 워싱턴발 규제성 발언이 시끄럽길래, 그게 실제 API 안정성에 영향을 주는지 보려고 했다 (출처: Google News, 검색어 "Anthropic", 기간 2026-05~06).
게다가, :::tip 외부 API를 의존성으로 쓰는 서비스라면, status 페이지 폴링은 50줄이면 끝난다. PagerDuty든 Opsgenie든 슬랙이든 어디로 보내든 상관없다. 핵심은 "장애 알림"이 아니라 "패턴 관찰"이다. 한 달치 누적되면 그제야 안 보이던 게 보이기 시작한다. :::
폴링 구조 — 30줄짜리 짧은 스크립트
물론, 별거 아니다. requests로 status JSON 가져오고, feedparser로 RSS 끌어오고, 같은 timestamp 키로 SQLite에 INSERT한다. 핵심은 두 데이터의 시간 정렬이다. 따로 모아두면 나중에 합칠 때 timezone에서 미끄러진다. 같은 process에서 같은 datetime.now()로 적는 게 가장 단순하다.
# status_watch.py — 60초 주기로 두 소스를 같이 적재
import time, sqlite3, requests, feedparser
from datetime import datetime, timezone
DB = sqlite3.connect("watch.db")
DB.execute("""
CREATE TABLE IF NOT EXISTS tick(
ts TEXT, status TEXT, headline_count INT
)
""")
STATUS_URL = "https://status.anthropic.com/api/v2/status.json"
NEWS_URL = "https://news.google.com/rss/search?q=Anthropic+when:1d"
while True:
ts = datetime.now(timezone.utc).isoformat()
# indicator는 none/minor/major/critical 중 하나
s = requests.get(STATUS_URL, timeout=10).json()["status"]["indicator"]
# 같은 시각의 24h rolling 헤드라인 개수
n = len(feedparser.parse(NEWS_URL).entries)
DB.execute("INSERT INTO tick VALUES (?, ?, ?)", (ts, s, n))
DB.commit()
time.sleep(60)
한편, GCP의 작은 e2-micro 인스턴스에 nohup으로 띄워뒀다. 한 달 누적 row가 약 4만 줄. 분석에 충분한 양은 아니지만 감을 잡기엔 된다.
그러나, 처음엔 cron으로 매분 호출하려다가 그만뒀다. requests session 재사용도 안 되고, RSS feed의 ETag도 못 쓴다. 그냥 while True가 단순하다.
새로 알게 된 것 — 헤드라인과 가용성은 거의 무관하다
본격적으로 본 건 며칠치였다. pandas로 SQLite를 읽어와서 headline_count의 1시간 이동평균과 status indicator를 나란히 찍어봤다. 헤드라인 곡선은 특정 발언 직후 가파르게 튀고, 그 다음 24시간 정도 고원처럼 유지된다. 반면 status indicator는 거의 평평하다. "none"이 대부분이고, 가끔 "minor"가 5~10분 찍히는 정도였다.
표본이 작아서 결정적 결론을 내릴 수준은 아니다. 한 달짜리 데이터로 인과관계를 주장하면 그게 더 위험하다. 다만 한 가지는 분명해 보인다 — 정치적 헤드라인이 늘어난다고 해서 API가 흔들리지는 않더라. Anthropic 입장에서 보면 당연한 결과다. 인프라는 인프라고, 정책 논쟁은 정책 논쟁이다. 두 축이 같은 시간 안에서 움직이긴 해도, 서로 영향을 주는 메커니즘이 거의 없다.
브랜드 검색량은 다른 이야기
이쯤에서 호기심이 발동했다. Google Trends에서 "Anthropic" 검색량을 같은 기간으로 끌어와 봤다 (출처: Google Trends, 2026-06 기준). 헤드라인이 튀는 시점과 검색량이 튀는 시점이 거의 겹친다. 규제성 발언이 나오면 검색량이 평소 대비 체감상 2~3배로 올라가고, 며칠 안에 baseline으로 돌아오는 패턴.
게다가, 흥미로운 건, 검색량 그래프가 위로 튀는 동안에도 우리 봇의 API 호출 패턴은 변하지 않았다는 점이다. 평소와 똑같이 돌아갔다. 즉, 헤드라인 → 브랜드 검색 → 신규 인지 유입은 가능해 보이지만, 헤드라인 → 기존 사용자 이탈은 일어나지 않더라.
| 축 | 규제 헤드라인 직후 변화 |
|---|---|
| API status indicator | 변화 없음 (none 유지) |
| 우리 봇 호출 성공률 | 변화 없음 |
| Google Trends "Anthropic" | 체감 2~3배 spike |
| 신규 인지 유입(추정) | 증가 패턴으로 보임 |
위 표는 한 달치 단일 봇 운영 관찰이다. 일반화는 신중해야 한다. 다른 워크로드, 다른 지역, 다른 규모에서는 다르게 나올 여지가 있다. 정작 더 흥미로운 건 표 자체보다 패턴의 비대칭성이다 — 부정적인 뉴스가 검색량을 끌어올리는 동안 사용량은 떨어지지 않는다. 브랜드 노출과 기술 신뢰는 별개 축이라는 게 자연스러운 해석으로 보인다.
정책 리스크와 기술 리스크는 다른 축
예를 들어, 이걸 보고 든 생각은 단순했다. 개발자가 외부 API를 의존성으로 끼울 때 봐야 하는 건 두 축이다 — 기술 리스크(가용성, latency, breaking change)와 정책 리스크(가격, 약관, 규제). 둘은 같은 회사에 묶여 있지만, 같은 시간대에 같이 움직이지 않는다.
물론, 규제 뉴스가 시끄럽다고 해서 API를 갈아끼울 이유는 거의 없다. 반대로, status 페이지가 잔잔하다고 정책 리스크가 0인 것도 아니다. 두 축을 분리해서 관찰해야 한다는 게 이번 주에 얻은 가장 큰 메모다.
조금 더 풀어보면, 기술 리스크는 status 페이지와 latency 로그에서 보이고, 정책 리스크는 약관 changelog와 규제 뉴스에서 보인다. 같이 한 대시보드에 올려두면 둘이 겹치는 순간이 잘 보인다. 보통은 한쪽만 움직인다.
코드 — 헤드라인과 status를 같이 보는 작은 대시보드
한편, 위 폴링 스크립트만으로는 뭐가 일어나는지 한눈에 안 보인다. 그래서 FastAPI로 미니 대시보드를 하나 더 띄웠다. /chart 엔드포인트가 한 달치 row를 그래프로 뿌려준다.
# dash.py — fastapi + plotly 2-line chart
from fastapi import FastAPI
from fastapi.responses import HTMLResponse
import sqlite3, pandas as pd, plotly.express as px
app = FastAPI()
@app.get("/chart", response_class=HTMLResponse)
def chart():
con = sqlite3.connect("watch.db")
df = pd.read_sql("SELECT * FROM tick ORDER BY ts", con)
df["ts"] = pd.to_datetime(df["ts"])
# indicator를 0/1/2/3으로 매핑
m = {"none": 0, "minor": 1, "major": 2, "critical": 3}
df["s_num"] = df["status"].map(m)
# 1시간 이동평균으로 노이즈 제거
df["hl_ma"] = df["headline_count"].rolling(60).mean()
fig = px.line(df, x="ts", y=["s_num", "hl_ma"])
return fig.to_html()
게다가, 이걸 켜고 며칠 보면 패턴이 보인다. 헤드라인 곡선은 산봉우리 같고, status 곡선은 거의 일직선이다. 시각적으로만 봐도 "두 축이 다르다"가 명확하다.
조심해야 할 부분 — RSS 카운트의 노이즈
따라서, Google News RSS는 같은 사건을 다루는 기사 수십 개를 동시에 토해낸다. 그래서 headline_count는 "사건의 크기"가 아니라 "기사화된 정도"에 가깝다. 이걸 그대로 신호로 쓰면 거품이 낀다.
해결책은 단순했다. headline 텍스트를 Claude Haiku에 던져서 "같은 사건끼리 묶어줘" 하는 짧은 분류를 돌렸다. 30분에 한 번씩만 호출하면 비용은 거의 무시할 수 있다. 결과를 보면 한 사건당 30~40개 기사가 따라붙는다. 이걸 dedupe하면 신호가 훨씬 깨끗해진다.
# 같은 사건끼리 묶는 분류 — 30분 주기
from anthropic import Anthropic
client = Anthropic()
def cluster(headlines: list[str]) -> str:
prompt = (
"아래 헤드라인들을 같은 사건끼리 묶어 JSON으로 반환해라. "
"key는 사건 요약, value는 헤드라인 인덱스 배열.\n\n"
+ "\n".join(f"{i}: {h}" for i, h in enumerate(headlines))
)
r = client.messages.create(
model="claude-haiku-4-5",
max_tokens=1024,
messages=[{"role": "user", "content": prompt}],
)
return r.content[0].text # JSON 파싱은 호출부에서
또한, 여기서 한 가지 알게 된 것 — Haiku가 짧은 분류 작업에서 의외로 단단하더라. JSON 형식만 시키면 거의 안 깨진다. 가격대를 생각하면 이런 보일러플레이트 분류는 Sonnet을 쓸 이유가 거의 없어 보인다 (공식 가격은 Anthropic Pricing 참고. 작성 시점 기준이다).
메모 — 다음에 해볼 것
따라서, 이번 주 TIL을 압축해 보면, 정치 헤드라인의 폭발은 브랜드 검색을 끌어올리지만 API 가용성과는 별개로 움직인다. 사용자 관점에서는 두 축을 분리해서 관찰해야 한다. Anthropic에 한정된 이야기가 아니라 OpenAI, Google AI 같은 다른 공급자에도 똑같이 적용될 가능성이 높다.
그런데, 지금 운영 중인 모니터링 구조에서 빠진 게 세 가지 있다.
- latency 트랙: status indicator는 "정상/장애" 이진에 가깝다. 실제 p95 응답 시간이 어떻게 움직이는지를 같이 봐야 한다. 우리 봇의 호출 latency를 같은 SQLite에 박아넣는 게 첫 번째 작업이다.
- breaking change 감지: API 응답 스키마가 미세하게 바뀌면 봇이 조용히 실패한다. JSON schema diff를 매일 한 번 자동 비교하는 cron을 붙이는 게 그다음이다.
- 약관 changelog 폴링: 정책 리스크 축을 잡으려면 status 페이지가 아니라 약관 페이지의 diff를 봐야 한다. 단순한 GitHub Actions cron으로 가능하다.
실제로, headline_count 분석은 흥미롭긴 한데 우리 비즈니스에는 직접 쓸모가 없다. 그저 "정책 리스크가 어떻게 생긴 모양인가"를 시각적으로 보기 위한 사이드 트랙이다. 우선순위를 다시 잡으면 latency 트랙이 먼저다. 다음엔 그걸 붙여볼 생각이다.
관련 글
- Anthropic IPO 수익성 회의론, Claude 쓰는 개발자가 본 반박 – AI 회사는 돈을 못 번다는 얘기가 IPO 시즌마다 반복된다. Anthropic도 예외가 아니다. 그런데 Claude API를 매일 결제하…
- MS-DOS 소스 공개 — Microsoft가 GitHub에 올린 진짜 이유와 Claude로 읽는 법 – Microsoft가 MS-DOS 1.25, 2.0, 4.0 소스를 GitHub에 푼 흐름을 짚는다. 직접 받아서 Claude로 어셈블리를 …
- FAANG 끝났다 – 이제는 MANGOS 시대, AI API 3개월 통합기 – 3개월 동안 사내 RAG 프로젝트에서 MANGOS 시대의 AI API들을 펼쳐놓고 비교했다. Claude를 메인으로, Gemini Flas…