라우팅 및 장애 조치: LLM 호출을 재시도하지 말아야 할 경우
요약
LLM API 호출 시 라우팅과 장애 조치(Failover)의 개념을 명확히 구분하는 것이 중요하며, 잘못된 방식으로 구현하면 오히려 서비스 품질 저하를 초래할 수 있습니다. 아키텍처 규칙으로 '경로는 한 번만 선택하고, 동등한 경우에만 장애 조치를 수행'해야 합니다.
핵심 포인트
- 라우팅과 장애 조치는 별개 개념이므로 혼동하지 않아야 함.
- 경로(Route)는 단일하게 선택하고, 모델 간의 실패 시에만 장애 조치를 고려해야 함.
- 정책에서 비밀 정보와 엔드포인트 관리를 분리하여 보안성을 높여야 함.
- 400 에러나 콘텐츠 필터 거부 같은 오류는 백업으로 재시도할 필요가 없음.
제가 검토하는 대부분의 LLM API는 IChatClient 하나와 기도에 불과합니다. 같은 모델로 "이 비동기 코드가 부하에서 왜 데드락 되는지"라는 질문을 보냅니다. 해당 제공업체가 20분 동안 503 오류를 반환하면, 제품도 그렇게 합니다.
라우팅(Routing)과 장애 조치(Failover) 모두 중요합니다. 이 둘을 혼동하는 것이 녹색의 가동 시간 차트와 더 나쁜 답변을 얻는 방법입니다. 전체 샘플(Microsoft.Extensions.AI 라우팅 유형, 회로 차단기, 테스트, 오프라인 프로필)은 Tech Skill Builder에서 확인할 수 있습니다. 여기서는 간략한 버전입니다: 몇 가지 중요한 규칙을 제시하고, 언제 장애 조치를 하지 말아야 하는지에 대한 Q&A를 제공합니다.
당신을 구원할 하나의 아키텍처 규칙
경로(Route)는 한 번만 선택하세요. 동등한 것들 사이에서만 장애 조치 하세요.
SemanticRoutingChatClient // 의미 → "deep" 또는 "fast" 경로 라우팅
└─ CircuitBreakingFailoverChatClient
├─ model A (timeout wrapper)
...
SemanticRoutingChatClient는 프롬프트를 임베드하고 각 경로별 예시 발화와 비교하여 점수를 매깁니다. 이후 장애 조치는 해당 경로의 순서가 지정된 모델 목록을 따라 진행됩니다. 계층을 뒤집으면 추론 모델에 문제가 생겼을 때, 작은 대화(small-talk) 모델로 어려운 디버깅 질문이 조용히 떨어질 수 있습니다. 가동 시간은 녹색으로 유지되지만, 품질은 그렇지 않습니다.
MEAI의 라우팅 및 장애 조치 유형은 10.x 버전에서 [Experimental("MEAI001")]로 표시됩니다. 따라서 선택 사항을 한 번만(예: Directory.Build.props에서) 설정하여 그 선택이 보이도록 해야 합니다.
구성 형태: 연결(Connections) / 모델(Models) / 경로(Routes)
정책에서 비밀 정보를 분리하세요:
| 섹션 | 포함 내용 |
|---|---|
Connections | 엔드포인트 및 키 (OpenAI, Azure, Ollama, 오프라인) |
| ... | |
| Rotating a key touches one connection. Swapping a model touches one entry. Routing policy never contains a secret, so you can review it in a PR without redacting. (키를 회전시키는 것은 하나의 연결을 건드립니다. 모델을 교체하는 것은 하나의 항목을 건드립니다. 라우팅 정책은 절대 비밀 정보를 포함하지 않으므로, 마스킹 없이 PR에서 검토할 수 있습니다.) |
시작 시 유효성 검사를 수행하세요. 알 수 없는 모델 이름, 누락된 기본 경로, 또는 여전히 YOUR_OPENAI_API_KEY로 설정된 활성 연결은 점심 식사 후 첫 요청이 아니라 배포 자체를 실패하게 해야 합니다.
builder.Services
.AddOptions<AiRoutingOptions>()
.BindConfiguration(AiRoutingOptions.SectionName)
...
Q&A: 언제 장애 조치(fail over)를 하지 말아야 할까요?
Q: 제공업체(provider)가 400을 반환했습니다. 백업(backup)으로 시도해 볼까요?
아니요. 잘못된 요청이나 스키마 오류는 다음 모델에서도 동일하게 실패할 것입니다. 같은 버그에 대해 두 번 비용을 지불하는 셈입니다.
Q: 콘텐츠 필터/정책 거부인가요?
아니요. 다음 공급업체(vendor)도 종종 동일한 프롬프트를 거부합니다. 이를 장애가 아닌, 해당 요청에 대한 최종 답변(그리고 제품/안전 신호)으로 취급해야 합니다.
Q: 401 / 잘못된 API 키인가요?
아니요. 같은 깨진 자격 증명(credential)으로 다른 모델로 장애 조치하는 것은 시간만 낭비합니다. 시크릿을 수정하세요. 교차 공급업체 백업은 그들의 자격 증명이 정상일 때에만 도움이 됩니다.
Q: 429, 5xx, 타임아웃(timeout), 연결 재설정(connection reset)인가요?
예. 그것들이 일시적인 경우입니다. 장애 조치하세요. 정책이 이를 분류할 수 있도록 TimeoutException으로 나타나는 시도당 타임아웃을 선호합니다 (요청 중단으로 인한 노출된 OperationCanceledException이 아닌).
분류기 아이디어의 골격:
static bool IsTransient(Exception ex) => ex switch
{
TimeoutException => true,
...
Q: 첫 토큰을 이미 스트리밍했습니다. 공급업체를 바꿀 수 있나요?
아니요. FailoverChatClient는 첫 번째 업데이트가 호출자에게 도달하는 순간 커밋(commits)됩니다. 절반의 답변을 되돌릴 수는 없습니다. 커밋된 후에는 실패가 해당 스트림에 대해 최종적입니다. UX를 그에 맞게 설계하세요 (부분 텍스트 + 명확한 실패 경로, 또는 중요 경로에서는 비스트리밍 방식).
Q: 동일한 모델이 연속으로 세 번 타임아웃되었습니다. 계속 시도하는 것이 좋을까요?
모든 요청에서 그럴 필요는 없습니다. 회로를 열어(Open a circuit) 일정 시간 동안 쉬게 하고, 해당 모델을 건너뛰었다가 나중에 다시 테스트하세요. 그렇지 않으면 공급업체가 알려진 문제가 있을 때마다 모든 호출이 완전한 타임아웃 비용을 지불하게 됩니다.
// CircuitBreakingFailoverChatClient : FailoverChatClient
protected override ValueTask<IChatClient> SelectClientAsync(...)
{
...
Q: 라우팅용 임베딩(Embeddings)이 다운되었습니다. 전체 API가 중단되어야 하나요?
기본 경로를 선호하세요. 시맨틱 라우팅은 최적화입니다. 임베딩에 실패하면, 채팅이 여전히 답변할 수 있도록 DefaultRoute (종종 fast)로 폴백(fall back)하세요. 소리 내어 로깅하고; 라우팅이 실행된 것처럼 가장하지 마세요.
배포 전 체크리스트
- [ ] 라우터 외부 장애 조치 (요청당 한 번 경로 지정)
- [ ] 장애 조치 목록 = 해당 경로에 대한 교체 가능한 모델들
- [ ] 일시적(Transient) 대 비일시적(non-transient) 분류기 (400 / 필터 / 인증 오류는 재시도하지 않음)
- [ ] 스트리밍 커밋먼트 존중
- [ ] 모델별 타임아웃 + 서킷 브레이커
- [ ] 연결/모델/경로 분리 +
ValidateOnStart - [ ] 응답에 경로, 모델, 시도 추적 기록 포함 (추측 없이 디버깅 가능)
- [ ] "항상 무언가를 답변"할 수 있도록 체인 내 오프라인 또는 로컬 백업
이 게시물에서 다루지 않는 내용
OrderedFailoverChatClient와 사용자 정의 FailoverChatClient 서브클래스를 연결하는 방법, 데모용 장애 주입 엔드포인트, 그리고 전체 옵션 검증기(options validator)는 완전한 프로젝트에 있습니다. 이것을 의사 결정 가이드로 사용하고; 오늘 밤에 dotnet test할 수 있는 것이 필요할 때는 리포지토리를 사용하세요.
만약 .NET에서 다중 모델 채팅(multi-model chat)을 구현한다면, 바로 사용할 수 있는 패키지는 Tech Skill Builder에 있습니다: 의미론적 라우팅 (semantic routing), 서킷 브레이킹 장애 조치 (circuit-breaking failover), 설정 검증(config validation), 그리고 API 크레딧을 소진하지 않고도 장애 상황을 연습할 수 있는 오프라인 프로필까지 제공합니다. 한정 기간 멤버십 가격은 제품 페이지에서 확인하세요. 이 패키지를 한번 구매하고, 에러 중 어떤 것이 두 번째 시도를 받을 자격이 있는지 재발명하는 데 시간을 낭비하기보다 프롬프트와 제품 자체에 시간을 투자하세요.
품질 없는 가동 시간(Uptime)은 거짓말입니다. 의미를 위해 경로를 지정하고, 동등한 모델들 사이에서 장애 조치를 하며, 치유되지 않을 실수들은 재시도하는 것을 거부해야 합니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기