요청은 성공했지만 경험은 실패했을 때
몇 주 동안 같은 캐릭터와 대화해 왔다고 상상해 보세요. 익숙한 말투, 일관된 언어, 영리하고 생생한 답변이 이어집니다.
그런데 캐릭터도 모델도 바꾸지 않았는데 갑자기 무언가 이상해집니다.
다음 답변이 시작되기까지 10초가 걸립니다. 구조화 출력에 의존하는 기능이 갑자기 동작하지 않습니다. 캐릭터가 횡설수설하거나 다른 언어 조각을 섞고, 훨씬 약한 모델로 바뀐 것 같은 말투로 답합니다.
서버 관점에서는 아무것도 실패하지 않았습니다. API는 200 OK를 반환했고 token이 도착했으며 요청 비용도 청구되었습니다.
사용자 관점에서는 모델이 갑자기 나빠졌습니다.
이 간극 때문에 우리는 Reverie에 제공자 카나리아 프로브와 라우팅 격리 시스템을 구축했습니다.
하나의 모델 이름, 여러 추론 환경
OpenRouter는 Reverie의 주요 모델 게이트웨이입니다. 하나의 모델을 여러 독립 추론 제공자가 서비스할 수 있다는 것이 큰 장점입니다. 한 제공자를 사용할 수 없으면 다른 곳이 요청을 처리할 수 있습니다. 단일 endpoint에 의존할 때보다 더 많은 용량, 경쟁력 있는 가격, 높은 복원력을 얻을 수 있습니다.
하지만 사용자가 볼 수 없는 변수도 생깁니다.
모델 이름은 그대로여도 실제로 모델을 실행하는 인프라는 요청마다 달라질 수 있습니다. 각 제공자는 서로 다른 추론 엔진, 하드웨어 구성, 양자화 수준, parser, 채팅 템플릿, 대기열 또는 추가 정책 계층을 사용할 수 있습니다.
OpenRouter의 제공자 라우팅 문서에 따르면 기본 라우팅은 최근 가용성과 가격을 고려하고 다른 제공자를 fallback으로 둡니다. 중요한 신호이지만, endpoint가 온라인이고 저렴하더라도 특정 제품에는 받아들일 수 없는 결과를 낼 수 있습니다.
OpenRouter 역시 같은 모델을 서비스하는 제공자 사이에 측정 가능한 차이가 존재한다는 사실을 공개적으로 설명했습니다. 이론적으로는 같은 정밀도의 동일 가중치가 비슷하게 동작해야 합니다. 그러나 대규모 모델을 프로덕션 환경에서 운영하는 일은 복잡하며 실제 차이가 발생합니다.
우리가 말하는 “모델 성능 저하”란
“모델 성능 저하”는 원인이 하나로 정해진 표준 진단명이 아닙니다. 제공자가 의도적으로 더 작은 모델로 바꿨다는 뜻도 아닙니다.
Reverie는 이를 운영 관점에서 정의합니다. 대표적인 prompt에서 요청한 모델에 기대되는 행동, 기능 또는 상호작용 성능을 추론 endpoint가 더 이상 유지하지 못한다면, 요청 자체가 기술적으로 성공했더라도 해당 endpoint는 저하된 상태입니다.
Reverie가 특히 주목하는 형태는 다음과 같습니다.
- 지연 시간 저하: 연결에는 성공하지만 첫 token까지 너무 오래 걸려 실시간 대화의 감각이 깨집니다.
- 기능 저하: 구조화 출력을 지원해야 하는 endpoint가 잘못된 텍스트를 반환하거나 schema를 충족하지 못합니다.
- 행동 저하: 답변이 손상되거나 일관성을 잃고, 비정상적으로 반복되거나 다른 언어로 뚜렷하게 이탈합니다.
- 정책 불일치: 상위 호스트가 자체 필터 계층을 추가해 Reverie가 지원하는 장면을 거부, 빈 응답 또는 잘린 답변으로 바꿉니다.
원인은 다양할 수 있습니다. 낮은 정밀도의 양자화가 어려운 prompt의 성능을 떨어뜨릴 수 있다는 점은 OpenRouter 문서와 공개된 양자화 연구 모두에서 확인됩니다. 하지만 양자화가 모든 문제를 설명하지는 않습니다. 추론 엔진이나 도구 parser의 버그, tokenizer 또는 채팅 템플릿 오류, 과부하된 대기열, 제공자 middleware도 똑같이 중요할 수 있습니다. OpenRouter는 도구 호출에서 정밀도 자체보다 parser 구현이 제공자 차이를 더 자주 만든다고 관찰했습니다.
중요한 질문은 “어떤 원인이 가장 수상해 보이는가?”가 아니라 “그 endpoint를 격리해 문제를 재현할 수 있는가?”입니다.
문제를 현실로 만든 두 가지 사례
이것은 이론적인 우려가 아니었습니다.
제공자를 고정한 비교 테스트에서 한 제공자는 20개 중 19개 답변의 시작 부분에 구두점이나 무관한 token 조각을 삽입했습니다. 같은 모델을 서비스하던 다른 14개 호스트에서는 총 49회 중 0회 발생했습니다. 롤플레이에서는 첫 글자가 Markdown 강조 표시인 경우가 많아, 불필요한 1 byte가 답변 전체의 서식까지 망가뜨릴 수 있었습니다.
또 다른 테스트에서는 한 endpoint가 3회 중 3회 심각한 포르투갈어-스페인어 혼용을 보였습니다. 같은 prompt는 모델 공식 호스트와 동일한 정밀도 등급의 다른 테스트 호스트에서 포르투갈어를 유지했습니다. “원래 모델은 일관되지 않다”는 설명으로는 부족했습니다. 결함이 특정 endpoint를 따라다녔기 때문입니다.
이런 장애는 반드시 예외를 일으키지 않기 때문에 알아채기 어렵습니다. 전통적인 가동 시간 모니터링에는 정상 API로 보이지만, 사용자는 캐릭터가 갑자기 제대로 말하지 못한다고 느낍니다.
우리의 대응: 모델이 아니라 모든 경로를 테스트하기
30분마다 카나리아 시스템은 Reverie 기본 채팅 모델을 서비스 중인 활성 제공자를 확인합니다. 그런 다음 fallback을 끄고 각 제공자 하나에만 고정한 작은 합성 요청 세트를 전송합니다.
경로 고정은 중요합니다. 프로브에 fallback이 허용되면 두 번째 정상 제공자가 첫 번째 제공자의 실패를 가릴 수 있습니다. 어떤 추론 환경이 결과를 만들었는지 정확히 알아야 합니다.
시스템은 코드로 판정할 수 있는 네 가지 좁은 계약을 검사합니다.
1. 첫 token까지의 시간
스트리밍 대화에서 throughput은 경험의 절반일 뿐입니다. 첫 token이 언제 나타나는지가 사용자가 로딩 화면을 보는 시간을 결정합니다.
우리는 stream에서 직접 측정합니다. 10초 안에 텍스트를 생성하지 못한 제공자는 지연 시간 프로브에 실패합니다. 임계값은 의도적으로 여유 있게 잡았고, 한 번 느린 것만으로 호스트를 제외하지 않습니다. 일시적인 대기열 압력은 발생할 수 있습니다.
2. 필터링과 조용한 거부
Reverie가 지원하는 실제 트래픽을 대표하는 고정 롤플레이 이어쓰기 요청을 보냅니다. 프로브는 종료 사유, 높은 신뢰도의 거부 패턴, 빈 출력을 확인합니다.
또한 필터링하는 것으로 알려진 호스트를 양성 대조군으로 사용합니다. 대조군이 예상과 달리 통과했다고 해서 나머지 제공자를 모두 정상으로 선언하지는 않습니다. 대신 프로브 자체가 약해졌다고 표시합니다. 이미 알려진 실패를 감지하지 못하는 테스트는 정상 상태의 증거가 아닙니다.
3. 구조화 출력
고정 schema를 가진 작은 객체를 요청하고 결과를 검증합니다. 전송 오류와 잘못된 출력은 다르게 처리합니다. 연결 실패는 제공자에 도달하지 못했다는 뜻이지만, 생성은 완료됐으나 schema를 만족하지 못한다면 기능이 퇴행했다는 증거입니다.
“endpoint가 이 parameter를 지원한다고 표시하는 것”과 “endpoint가 이를 안정적으로 지키는 것”은 같은 약속이 아닙니다.
4. 언어 무결성
Reverie는 17개 인터페이스 언어를 지원합니다. 영어만 확인하는 smoke test로는 사용자가 실제로 겪는 장애 일부를 놓치게 됩니다.
카나리아는 합성 롤플레이 prompt로 지원 언어를 돌아가며 검사합니다. 로컬에서 동작하는 결정론적 언어 감지기가 응답 전체의 명확한 언어 전환, 지속적인 언어 혼용, 뚜렷한 인코딩 손상을 찾습니다. 실제 대화를 사용하지 않으며, 다른 모델에게 주관적인 판단을 요청하지도 않습니다.
모호하거나 너무 짧은 출력은 실패가 아니라 판단 불가로 처리합니다. 언어 이상을 발견하면 즉시 두 번 더 확인하고 세 번 중 다수가 실패해야 합니다. 다음 라운드에서도 같은 언어를 반복하므로, 언어 순환이 넘어갔다는 이유만으로 연속 라운드 규칙을 피할 수 없습니다.
시스템 스스로의 결론도 의심하도록 설계하기
추론 용량을 자동으로 제거하는 것은 유용하지만, 오탐은 원래 결함보다 더 큰 장애를 만들 수 있습니다. 그래서 카나리아에는 여러 안전장치가 있습니다.
- 전송 오류는 품질 실패로 계산하지 않습니다. timeout, rate limit, 5xx 응답은 격리 연속 횟수를 늘리지 않고 점수를 동결합니다.
- 한 번의 실패로는 부족합니다. 제공자는 30분마다 실행되는 두 라운드에서 연속 실패해야 합니다.
- 관찰과 집행을 분리합니다. 관찰 모드에서 어떤 호스트가 격리될지 기록하고 관리자에게 알리며 오탐률을 확인한 뒤 자동 조치를 켤 수 있습니다.
- 용량에는 하한선이 있습니다. 격리 후 프로덕션 호스트가 두 개 미만으로 남는다면 카나리아는 제공자를 격리하지 않고 관리자에게 알립니다.
- 복구도 테스트합니다. 격리된 제공자에도 계속 프로브를 보내며 두 라운드 연속 완전히 통과하면 조기에 복구합니다.
- 반복 실패는 단계적으로 강화합니다. 첫 번째 격리는 1일, 다음은 3일, 이후는 7일입니다. 새 격리 없이 14일이 지나면 이력의 영향이 사라지고 다시 1일부터 시작합니다.
목표는 제공자를 처벌하는 것이 아닙니다. 재현 가능한 비정상 경로에서 사용자 트래픽을 빼고, 문제가 해결됐을 때 돌아올 수 있는 명확한 길을 남기는 것입니다.
세 겹의 보호
최종 라우팅 결정에는 세 종류의 제외 항목이 합쳐집니다.
- 검토된 내장 제외 항목: 이미 측정한 결함이나 정책 불일치가 실수로 다시 들어오지 않게 합니다.
- 런타임 사고 대응 제외 항목: 관리자가 배포를 기다리지 않고 즉시 추가할 수 있습니다.
- 카나리아의 시간제 격리 항목: 자동 실패 임계값을 넘은 제공자에게 적용됩니다.
Reverie가 요청을 구성할 때 이 목록들은 OpenRouter의 provider.ignore 설정으로 합쳐집니다. 사용자는 우연히 더 나은 제공자가 선택될 때까지 재시도할 필요가 없습니다. 비정상 경로 자체가 후보에서 제외됩니다.
모든 자동 결정은 감사 기록에 남고, 중요한 상태 전환은 관리자에게 통지됩니다. 필요할 때는 수동으로 격리를 해제할 수도 있습니다.
이 시스템이 보장하는 것과 보장하지 않는 것
카나리아의 판단 범위는 의도적으로 좁습니다. 지연 시간, schema 유효성, 높은 신뢰도의 필터링, 언어와 인코딩 무결성은 코드로 판단할 수 있습니다. 하지만 캐릭터가 충분히 재미있는지, 감정을 섬세하게 이해하는지, 복잡한 성격을 충실히 지키는지 점수화할 수 있는 척하지 않습니다.
이런 더 넓은 질문에는 대표 prompt를 활용한 평가, 사람의 검토, 프로덕션 telemetry, 그리고 무엇보다 사용자 신고가 여전히 필요합니다.
또한 이상한 답변 하나가 곧 모델 성능 저하를 증명하지는 않습니다. 생성형 모델은 확률적입니다. 긴 대화에는 충돌하는 맥락이 쌓일 수 있고 캐릭터 정의에 서로 경쟁하는 지시가 들어 있을 수도 있습니다. 때로는 이상한 답변이 그저 한 번의 이상한 답변일 뿐입니다.
달라진 점은 이제 “같은 모델”이라는 이유로 조사를 끝내지 않는다는 것입니다. 실제 서비스 경로를 격리하고 객관적인 실패를 재현하며 이후 트래픽을 그 경로에서 멀리 보낼 수 있습니다.
안정성이란 경험을 지키는 것
여러 제공자를 활용하는 라우팅은 여전히 가치가 큽니다. 개별 endpoint가 중단되어도 Reverie가 대화를 계속 제공할 수 있는 용량과 복원력을 줍니다.
하지만 복원력은 단순히 HTTP 응답을 받는 것만을 뜻하지 않습니다. 너무 늦게 시작하고, 필요한 구조를 잃고, 지원되는 콘텐츠를 거부하거나 갑자기 언어를 바꾸는 답변은 청구서에 “성공”으로 적혀 있어도 정상 결과가 아닙니다.
AI 캐릭터 제품에서 안정성은 조금 더 인간적인 의미를 가집니다. 어떤 기계가 대신 말하더라도 캐릭터는 계속 그 캐릭터답게 느껴져야 합니다.
Reverie의 새로운 라우팅 보호 장치는 바로 그 기준을 지키기 위해 만들어졌습니다.
답변 품질이나 언어가 갑자기 달라졌다면 모델 이름과 대략적인 시간을 함께 알려 주세요. 여러분이 본 경험을 당시 실제로 응답한 경로와 연결하는 데 큰 도움이 됩니다.

