작은 Python 상태 머신(State Machine)으로 장애 폴백(Outage Fallback) 배우기
요약
API 타임아웃 발생 시 안전한 장애 폴백(Fallback)을 구현하기 위한 Python 상태 머신 설계 방법을 다룹니다. 타임아웃이 작업 완료를 보장하지 않음을 지적하며, 중복 작업을 방지하기 위한 UNKNOWN 상태의 중요성을 강조합니다.
핵심 포인트
- 타임아웃은 서버의 작업 완료 여부를 보장하지 않음
- 상태 머신을 통해 안전한 폴백 전환 로직 모델링 가능
- 중복 실행 방지를 위해 UNKNOWN 상태와 검증 단계 필요
- 모델 간의 의미론적 차이(Semantic Risk) 고려 필수
모델에 작업을 보낸 후 타임아웃(timeout)이 발생했다고 가정해 봅시다. 다시 보내는 것이 안전할까요? 초보자들의 놀라운 답변은 "아직은 안 됩니다"입니다. 왜냐하면 타임아웃은 클라이언트가 관찰한 현상을 설명하는 것이지, 서버가 작업을 완료했는지를 설명하는 것이 아니기 때문입니다.
실제 타임라인을 통해 이 교훈을 구체화해 보겠습니다. OpenAI는 7월 25일의 한 사고가 09:17:49 UTC에 시작되어, 10:02:52에 완화 모니터링(mitigation monitoring) 단계에 도달했고, 11:08:36에 해결되었다고 보고했습니다. 또 다른 사고는 11:35:24에 시작되었습니다. 조사 당시, 두 번째 사고는 오류 증가와 완화 조치가 진행 중인 것으로 식별되었습니다. 상태 사이트에는 '부분적 시스템 저하(Partial System Degradation)'라고 표시되었습니다. 이러한 사실만으로는 근본 원인(root cause), 전 세계적 영향 범위, 정확한 피해자 수, 또는 나중에 발생한 이벤트가 최종적으로 어떻게 종료되었는지는 알 수 없습니다.
우리는 어떤 API를 호출하지 않고도 안전한 선택들을 모델링할 수 있습니다.
전제 조건 및 상태 (Prerequisites and states)
Python 3.11 이상이 필요합니다. 아래의 전체 예제는 실행되지 않은(unexecuted) 상태이므로, 출력값은 테스트 결과가 아닌 예상 출력값(expected output)입니다.
from dataclasses import dataclass
from enum import Enum, auto
...
이 드라이버(driver)를 시도해 보세요:
job = Task()
job.send('attempt-1')
job.timeout()
...
예상 출력:
SWITCH_READY alternate
중요한 중간 상태는 UNKNOWN입니다. 타임아웃에서 폴백(fallback)으로 직접 건너뛰면 작업이 중복될 수 있습니다. reconcile_missing()이라는 이름은 실제 애플리케이션이 시도를 교체하기 전에 제공자 조회(provider lookup)나 운영자의 결정과 같은 증거가 필요하다는 점을 상기시키기 위해 의도적으로 명명되었습니다.
하나의 오류 입력
새로운 작업을 구성한 후 다음을 실행하세요:
Task().choose_fallback('alternate')
예상 결과: ValueError: pause before switching. 만약 실패하지 않는다면, 해당 상태 머신은 검토되지 않은 제공자 변경을 허용하는 것입니다.
두 번째 제공자(provider)를 사용하는 것은 단순히 새로운 엔드포인트(endpoint)를 사용하는 것을 넘어 의미론적 위험(semantic risk)을 초래합니다. 모델들은 동일한 프롬프트(prompt)를 다르게 해석하거나, 서로 다른 도구(tools)를 지원하거나, 호환되지 않는 구조화된 데이터(structured data)를 생성할 수 있습니다. 학습을 확장하려면 VALIDATING 상태를 추가하고, DONE 상태에 도달하기 전에 세 가지의 제공자 중립적인 피스처(fixtures)를 요구하도록 구성할 수 있습니다.
흔한 실수로는 상태 페이지(status-page)의 색상을 재시도(retry) 명령으로 취급하는 것, 상태 전이(transitions) 대신 현재 상태만을 저장하는 것, 그리고 다른 모델이 의미를 그대로 보존할 것이라고 가정하는 것 등이 있습니다. 실제 프로그램에서는 각 전이(transition)를 해당 요청 ID(request ID)와 함께 영속화(persist)해야 합니다.
더 큰 시스템을 조사하는 두 가지 방법
이 장난감 머신(toy machine)을 이해한 후, 학습자들은 해외의 MonkeyCode 호스팅 옵션을 평가해 볼 수 있습니다. 해당 페이지에는 현재 “Start free”라고 표시되어 있습니다. 공식 README에서는 빌드(build), 테스트(test), 프리뷰(preview) 기능과 통합된 모델을 갖춘 관리형 서버 측 클라우드 환경(managed server-side cloud environments)을 설명합니다. 현재는 무료로 시작할 수 있으나, 모델/서버 할당량(quotas), 지역(regions), 가동 시간(uptime) 또는 SLA 세부 사항은 변경될 수 있으므로 콘솔에서 확인해야 합니다.
정확한 공식 MonkeyCode 리포지토리는 AGPL-3.0 오픈 소스입니다. 메인 커밋 18baaf54937a65a7d47f1f9d83dd808777aa6cea에서 README는 개발 환경, 모델, 작업(tasks) 및 요구 사항(requirements)에 대한 내장된 관리 기능을 설명합니다. 저는 이 리포지토리를 조사용 소스 자료이자 가능한 셀프 호스팅(self-hosting) 탈출 옵션으로 보고 있으며, 장애(outages)에 대한 보증책으로 보지는 않습니다. 호스팅된 MonkeyCode의 신뢰성은 이 기사를 위해 테스트되지 않았습니다.
유용한 연습 방법은 장난감 상태(toy states)를 리포지토리 개념에 매핑한 다음, 민감하지 않은 호스팅 작업 하나를 시도하며 모든 가정을 기록해 보는 것입니다. 학습 관련 주장(learning claims)과 운영 관련 주장(operational claims)을 분리하여 유지하십시오.
공개 사항: 저는 MonkeyCode 사용자로서 저의 경험을 공유하는 것이며, 해당 프로젝트와 관계가 없습니다.
AI 지원 공개: 이 기사는 AI의 도움을 받아 초안을 작성하였으며, 인용된 1차 자료를 바탕으로 검토되었습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기