모델이 나빠진 걸까요, 아니면 기분 탓일까요? LLM API가 조용히 변경되었을 때 실제로 확인하는 방법
요약
LLM API의 성능 변화가 모델 자체의 문제인지, 혹은 환경 변화 때문인지 객관적으로 검증하는 방법을 제시합니다. 고정된 프롬프트 세트인 '카나리 스위트'를 구축하고 정량적 지표를 기록하여 변화를 감지하는 체계를 제안합니다.
핵심 포인트
- 모델 성능 저하를 직관이 아닌 데이터로 검증해야 함
- 고정된 프롬프트 세트(Canary Suite)를 구축하여 기준점 확보
- JSON 유효성, 출력 길이 등 계산 가능한 저렴한 스칼라 지표 활용
- 문제가 발생하기 전부터 주기적인 테스트와 데이터 기록 필수
당신은 gpt-x 또는 claude-y를 기반으로 기능을 출시했습니다. 잘 작동합니다. 3주 후, 사용자들은 출력이 더 나빠진 것 같다고 말합니다 — 더 모호하고, 더 엉성하며, 예전에는 통과했던 동일한 프롬프트(prompts)에서도 실패합니다. 당신은 코드를 변경하지 않았습니다. 모델이 변한 걸까요, 아니면 당신의 착각일까요?
이 질문은 놀라울 정도로 많은 엔지니어링 시간을 잡아먹으며, 거의 항상 '느낌(vibes)'에 대한 논쟁으로 끝납니다. 한쪽에서는 "분명히 나빠졌다"라고 말하고, 다른 한쪽에서는 "증거가 없다, 확증 편향(confirmation bias)이다"라고 말합니다. 양쪽 모두 맞습니다. 왜냐하면 누구도 이 문제를 해결할 수 있는 단 한 가지 요소를 측정(instrumented)하지 않았기 때문입니다. 여기 그 문제를 해결하는 방법이 있습니다.
왜 여기서 당신의 직관은 쓸모가 없는가 (단일 비교도 마찬가지입니다)
호스팅된 모델이 "나빠진 것 같다"고 느껴질 때는 두 가지가 동시에 움직입니다:
- 제공자(provider) 측면 — 새로운 체크포인트(checkpoint), 라우팅(routing) 변경, 추론 최적화(inference optimization) (배칭(batching), 투기적 디코딩(speculative decoding), 양자화(quantization)), 또는 인프라 버그. 이러한 일이 언제 발생하는지는 통보받지 못합니다. 종종 제공자는 이를 발표하지 않으며, 때로는 모델 변경조차 아닌 인프라 회귀(regression)가 모델이 멍청해진 것처럼 보일 뿐일 때도 있습니다.
- 당신 측면 — 프롬프트(prompt) 수정, 온도(temperature) 변경, 새로운 라이브러리 버전, 다른 컨텍스트 길이(context length), 또는 단순히 오늘 우연히 마주친 프롬프트들.
몇 가지 일화적인 프롬프트에 대해 단일 계정으로 확인하는 것으로는 이 두 가지를 구분할 수 없습니다. 그것이 함정입니다. 이 함정에서 벗어나려면 두 가지가 필요합니다: 객관적이고 날짜가 기록된 신호(dated signal), 그리고 "나에게만 변한 것"과 "모두에게 변한 것"을 구분할 방법입니다.
1단계 — 카나리 스위트(canary suite) 고정하기
당신이 실제로 의존하는 역량들을 테스트할 수 있는 작고 고정된 프롬프트 세트 — 20개에서 100개 사이 — 를 선택하세요. 작고 저렴하게 유지하십시오. 이것은 벤치마크(benchmark)가 아니라 연기 감지기(smoke detector)입니다. 이를 고정하십시오: 동일한 프롬프트, 동일한 파라미터(temperature, top_p, max_tokens), 동일한 모델 문자열(model string), 영원히 말입니다. 스위트를 변경하는 순간 기준점(baseline)을 잃게 됩니다.
각 카나리(canary)에 대해, 자동으로 계산할 수 있는 **저렴한 스칼라(cheap scalar)**를 정의하십시오:
- JSON/스키마 유효성 비율 (JSON/schema validity rate, 파싱 가능하고 유효한 출력을 반환했는가?)
- 출력 길이 (Output length, 갑작스러운 변화는 종종 품질 변화의 전조가 됩니다)
- 고정된 단언(assertion)에 대한 통과/실패 여부 (작성된 함수가 컴파일되는가?)
- 저렴한 채점자(cheap grader)로부터 얻은 루브릭 점수 (rubric score)
당신은 추상적인 의미에서의 "품질"을 측정하려는 것이 아닙니다. 당신은 "변화"를 감지하려는 것입니다. 지루하고 안정적인 스칼라(scalar)가 바로 당신이 원하는 것입니다.
2단계 — 상황이 좋을 때 기준선(baseline)을 기록하십시오
일정 주기(매시간, 매일 등 예산이 허용하는 범위 내에서)로 테스트 스위트를 실행하고 (timestamp, prompt_id, metric)를 저장하십시오. 무언가 의심하기 전에 이 작업을 수행해야 합니다. 기준선이 게임의 핵심입니다. "지난달의 정상적인 상태가 어떠했는지"가 없다면 오늘과 비교할 대상이 아무것도 없게 됩니다. 안정적인 기간 동안 프롬프트별 메트릭(metric)의 평균 μ₀와 표준 편차 σ₀를 추정하십시오.
3단계 — 임계값(threshold)이 아닌 변화점 테스트(change-point test)를 실행하십시오
고정된 임계값("성공률이 90% 미만이면 경고")은 노이즈가 심하고 대응이 늦습니다. 당신에게 필요한 것은 작고 일관된 변화를 축적하여 타임스탬프와 함께 알람을 울리는 **순차적 변화점 탐지기(sequential change-point detector)**입니다. 고전적인 방법은 CUSUM (Page, 1954)입니다. 코드는 몇 줄 되지 않습니다:
def cusum_alarm(values, mu0, sigma0, k=0.5, h=5.0):
"""표준화된 관측값에 대한 양방향 CUSUM.
k = slack (표준 편차 단위), h = 알람 임계값.
...```
시간 경과에 따른 프롬프트별 메트릭을 입력하십시오. 이제 "느낌상 나빠졌다" 대신, "#14번 프롬프트의 json_success_rate가 화요일부터 하락했다"라는, 티켓(ticket)에 기재할 수 있는 날짜가 포함된 주장을 할 수 있게 됩니다. (`h=5.0`, `k=0.5`는 표준화된 데이터에 대한 합리적인 시작점이며, 자신의 이력에 따라 조정하십시오. 사후 확률(posterior probabilities)을 원한다면 베이지안 온라인 변화점 탐지(Bayesian Online Change-Point Detection)가 더 정교한 대안이 될 수 있습니다.)
이것만으로도 당신은 단순한 일화(anecdote) 수준에 머물러 있는, "모델이 나빠졌다"라고 주장하는 스레드의 약 95%보다 앞서 나가게 됩니다.
## 4단계 — 혼자만의 생각인지 절대 답할 수 없는 부분: "나만 그런 걸까?"
당신이 마주하게 될 한계는 다음과 같습니다. 완벽한 변화 지점(change-point) 신호가 있더라도, **공급자 측의 변경과 자체적인 드리프트(drift)를 구분할 수 없습니다.** 한 곳의 관점에서는 두 현상이 동일하게 보이기 때문입니다. CUSUM(누적합) 신호가 발생했을 때, 그것이 모델 때문인지, 지난주에 수행한 LlamaIndex 업데이트 때문인지, 아니면 불안정한 리전(region) 때문인지 알 수 없습니다.
이 둘을 분리할 수 있는 유일한 방법은 **독립적인 관찰자들 간의 상관관계(correlation)**입니다. 만약 당신의 카나리(canary)가 화요일에 작동했고, *동일한* 모델을 *동일한* 지표로 관찰하고 있는 *다른* 여러 조직들도 화요일쯤 신호를 보냈다면, 그 일치성이 바로 이것이 당신의 테스트 환경(harness)이 아닌 공급자 측의 문제라는 신호가 됩니다. 단일 관찰자는 영원히 N=1에 머물러 있으며, 이것이 바로 이러한 스레드들이 결론에 도달하지 못하는 이유입니다. 이것은 진정으로 다른 종류의 탐지 방식입니다. 즉, "내 앱을 모니터링한다"(모든 관측성(observability) 도구가 하는 일)가 아니라, "이 변화가 *모두에게* 일어났는가? 플릿(fleet) 전체에서 비공개적으로 확인되었는가?"를 묻는 것입니다.
이러한 교차 관찰자(cross-observer) 관점이 바로 [SEISMOGRAPH](https://github.com/Tania-coder/SEISMOGRAPH)가 구축된 핵심 원리입니다. 경량 프로브(probe)가 카나리 스위트(canary suite)를 실행하고, 변화 지점 탐지기(change-point detector)가 로컬에서 변화를 표시하며, 프롬프트나 출력값은 절대 공유하지 않고 오직 개인정보를 보호하는 분포 특징(distributional features)만을 공유합니다. 따라서 공개적인 "모델 날씨(model weather)" 경보가 울리는 경우는 오직 *여러 독립적인 관찰자들이 일치할 때*뿐입니다. 단일 조직의 신호는 비공개로 유지됩니다.
## 이것이 실제로 작동할까요? 실제 사례
이 방법은 가설에 그치지 않습니다. 2025년 9월 Anthropic 사고를 예로 들어보겠습니다. 일정 기간 동안 `claude-sonnet-4`의 성능이 저하되었는데, 이는 모델 업데이트가 아니라 인프라 버그 — 특히 컨텍스트 윈도우(context-window) 라우팅 오류 — 때문이었습니다 (Anthropic은 [사후 분석 보고서(postmortem)](https://www.anthropic.com/engineering/a-postmortem-of-three-recent-issues)에서 이를 명시적으로 밝혔습니다). 이는 이 글 전체가 다루고 있는 "모델 문제인가, 인프라 문제인가?"라는 안개와 정확히 일치하는 사례입니다.
위에서 설명한 CUSUM 방법을 사용하여 해당 기간 동안 카나리 스위트 (canary suite)를 다시 실행해 본 결과: **시드(seeded)를 설정한 백테스트 (backtest)는 사후 분석 (postmortem)이 이루어지기 38일 전에 이를 감지했습니다.** 실시간 포착은 아니었지만 — 시드가 설정된 공개적이고 재현 가능한 백테스트였지만 — 이는 공식적인 인정이 있기 훨씬 전부터 저렴한 분포 지표 (distributional metrics) 안에 신호가 머물고 있었음을 보여줍니다.
## 직접 해보기
- **Probe (오픈 소스, Apache-2.0):** `pip install seismograph-probe`
- **실시간 "모델 날씨" 대시보드:** [https://driftdefense.dev?utm_source=devto&utm_medium=article&utm_campaign=evergreen_howto](https://driftdefense.dev?utm_source=devto&utm_medium=article&utm_campaign=evergreen_howto)
- **코드 + 방법론:** [https://github.com/Tania-coder/SEISMOGRAPH](https://github.com/Tania-coder/SEISMOGRAPH)
시작하는 데 이 모든 것이 필요한 것은 아닙니다. 위의 네 단계는 크론 잡 (cron job), CSV, 그리고 10줄의 CUSUM만으로도 작동합니다. 하지만 "단순히 나만의 문제인가?"라는 질문에 대한 답을 얻고 싶다면, 한 명 이상의 관찰자가 필요하며, 바로 그 부분이 연합 (federating)할 가치가 있는 부분입니다.
## FAQ
**GPT / Claude / Gemini가 최근에 실제로 성능이 저하되었나요?**
때로는 그렇기도 하고, 때로는 사용자의 설정 문제일 수도 있으며, 많은 경우 "더 나쁜 모델"이 아니라 제공업체 측의 인프라 (infra) 변경 때문입니다. 이 글의 핵심은 느낌 (vibes)에 따라 답하지 말고, 계측 (instrument)을 통해 날짜가 명시된 신호를 얻어야 한다는 것입니다.
**호스팅된 모델이 변경되었다는 것을 어떻게 증명할 수 있나요?**
단일 계정만으로는 이를 "증명"할 수 없지만, 강력한 객관적 증거를 확보할 수는 있습니다. 고정된 카나리 스위트 (canary suite) + 베이스라인 (baseline) + 변화점 테스트 (change-point test)를 결합하면 날짜가 기록된 변화를 얻을 수 있습니다. 제공업체 측 드리프트 (provider-side drift)와 로컬 드리프트 (local drift)는 여러 독립적인 관찰자들 사이의 일치 여부를 통해서만 분리할 수 있습니다.
**이것은 단순히 LLM 관측성 (observability) / 평가 (evals) 아닌가요?**
관련은 있지만 다릅니다. 평가 (Evals)는 특정 시점의 품질을 점수화하고, 관측성 (observability)은 "사용자의" 트래픽을 모니터링합니다. 이것은 당신이 제어할 수 없는 호스팅된 종속성 (dependency)에서 발생하는 "시간에 따른 변화"를 감지하는 것에 관한 것이며, 독특하게도 "단순히 나만의 문제"를 배제하기 위해 조직 간에 해당 변화를 상관 분석 (correlating)하는 것에 관한 것입니다.
**어떤 지표를 추적해야 할까요?**
품질 변화에 따라 함께 움직이는 가장 저렴한 지표부터 시작하세요: 스키마/JSON 유효성 (schema/JSON validity), 출력 길이 (output length), 그리고 카나리 (canary)당 단일 고정 통과/실패 (pass/fail) 여부입니다. 더 높은 해상도 (resolution)를 원한다면 나중에 루브릭 점수 (rubric score)를 추가하세요.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기