Stop guessing auto scaling targets for TTS on Amazon SageMaker AI
Quick Summary
Amazon SageMaker AI에서 Kokoro 82M의 자동 확장 목표를 추측 대신 단일 인스턴스의 동시 요청 한계 Q max와 실제 확장 시간 T total의 실측값으로 정하는 방법을 설명하며, 제공된 본문에서는 Q max = 50과 T total 측정의 일부 결과까지 확인된다.
🖼️ 인포그래픽

🖼️ 4컷 인포그래픽

💡 한 줄 요약
Amazon SageMaker AI에서 Kokoro-82M의 자동 확장 목표를 추측 대신 단일 인스턴스의 동시 요청 한계 Q_max와 실제 확장 시간 T_total의 실측값으로 정하는 방법을 설명하며, 제공된 본문에서는 Q_max = 50과 T_total 측정의 일부 결과까지 확인된다.
📌 핵심 요약
- Kokoro-82M은 8,200만 매개변수의 TTS 모델로, 사용자 정의 컨테이너와 세 개의 AWS CDK 스택을 통해 Amazon SageMaker AI 실시간 엔드포인트에 배포된다. 자동 확장 리소스는 scaling_enabled 조건과 실제 측정에 기반한 실행 가능한 plan 산출물이 모두 있어야 생성된다.
- 자동 확장 지표는 Amazon SageMaker AI가 기본 제공하는 ConcurrentRequestsPerModel이다. 도구는 클라이언트의 평균 처리 중 요청 수와 이 지표의 10초 구간 Maximum 통계 사이 비율을 측정하며, 본문의 실행에서는 모든 동시성 단계에서 비율이 정확히 1.0이었다.
- 단일 인스턴스에서 p95 첫 오디오 바이트 도달 시간의 SLO를 3,000ms로 설정한 결과, 동시 요청 50개에서는 2,805.7ms로 충족했고 60개에서는 3,374.8ms로 위반해 Q_max = 50으로 정했다. 대기 없는 요청의 처리 시간은 평균 61.3ms, p95 66.1ms였다.
- T_total은 용량 추가 요청부터 새 용량이 정상 트래픽을 처리할 때까지의 실제 확장 시간이다. 제공된 본문은 8단계 중 일부에서 끊기며, 인스턴스가 로그에 나타나기까지의 구간이 180.8초로 전체의 56.5%를 차지했다는 결과는 있지만 전체 시간과 최종 확장·축소 임계값 및 쿨다운 수치는 확인되지 않는다.
- 측정 전 drift로 배포 상태와 설정을 대조하고, 중단된 측정 때문에 용량이 고정되어 있으면 thaw로 복구한다. 실습에는 기준 용량보다 최소 한 슬롯 여유가 있는 ml.g5.xlarge 할당량 등이 필요하며, 샘플의 PyTorch 고정 버전에는 PYSEC-2026-2286이 있어 개념 검증을 넘어 사용하기 전에 검토와 업그레이드가 필요하다.
🧩 주요 포인트
- Q_max = 50은 지연 SLO 안에서 감당한 동시성의 측정값이고 T_total은 증설 지연의 측정값이므로, 두 값이 용량 여유와 확장 시점 및 쿨다운을 산정하는 근거가 된다.
- scaling_enabled만으로는 측정 여부를 보장하지 못하므로, 실행 가능한 plan의 존재를 추가 배포 조건으로 삼아 미측정 자동 확장 설정의 적용을 막는다.
- ConcurrentRequestsPerModel의 기본 제공과 클라이언트 측정값의 단위 보정은 지표 미발행과 통계 불일치 위험을 줄이며, 이번 실행의 비율 1.0은 해당 측정 조건에서 두 임계값이 일치했음을 뜻한다.
🧠 상세 정리
1. 추측한 자동 확장 목표가 만드는 비용과 지연 위험
글은 자체 호스팅 TTS 엔드포인트에 트래픽이 몰리면 요청이 대기하고, 이용자가 가장 많은 순간에 지연이 서비스 수준 목표인 SLO를 넘어서는 문제에서 출발한다. 자동 확장 정책이 있어도 목표값을 추측으로 정했다면 실제 부하가 발생할 때까지 문제가 드러나지 않을 수 있다. 지나치게 보수적인 설정은 대부분 유휴 상태인 GPU 인스턴스의 비용으로 이어지고, 지나치게 공격적인 설정은 인스턴스가 지연 약속 안에 처리할 수 있는 것보다 많은 요청을 떠안게 한다. 전자는 청구서에 반영되지만 사고 보고로 이어지지 않고, 후자는 트래픽 급증 시 대기 시간이 늘어나면서 현실화된다는 설명이다. 이를 해결하기 위해 글은 실제 엔드포인트에서 동시성 한계 Q_max와 확장 소요 시간 T_total을 측정하고, 두 수치로 확장·축소 임계값과 양쪽 쿨다운을 산정하는 접근을 제시한다.
2. TTS에 맞는 동시 요청 지표와 통계 보정
글은 짧은 동기식 요청·응답이나 초당 생성 토큰 수를 중심으로 한 LLM 서빙 지침이 TTS에 그대로 들어맞지 않는다고 설명한다. Kokoro-82M은 ISTFTNet 디코더를 사용하는 StyleTTS2 계열의 비자기회귀 모델로, 적대적 학습을 거쳐 길이가 정렬된 한 번의 처리로 전체 발화를 생성하므로 토큰별 계측을 붙일 생성 루프가 없다. 따라서 과부하 판단에는 현재 대기 중이거나 실행 중인 요청 수가 중요하며, 정책은 Amazon SageMaker AI가 직접 발행하는 ConcurrentRequestsPerModel을 사용한다. 이 지표는 10초 구간의 Maximum 통계이므로 클라이언트가 직접 측정하는 평균 처리 중 요청 수와는 다른 양이고, 도구는 각 동시성 단계에서 같은 부하에 대한 두 값의 비율을 기록해 임계값을 Amazon CloudWatch 단위로 변환한다. 본문의 Kokoro-82M 실행에서는 모든 단계의 비율이 정확히 1.0으로 나와 별도의 수치 차이 없이 임계값이 일치했다.
3. 사용자 정의 컨테이너와 두 가지 스트리밍 전송
솔루션은 8,200만 매개변수의 Kokoro-82M을 사용자 정의 컨테이너에 넣고 Amazon SageMaker AI 실시간 엔드포인트에 배포한다. 합성 요청은 클라이언트에서 엔드포인트로 들어온 뒤 GPU 인스턴스의 컨테이너를 거쳐 내부 모델로 전달되는 네 계층을 통과한다. 컨테이너는 합성 중인 오디오를 돌려주어 발화가 끝나기 전에 재생을 시작할 수 있는 InvokeEndpointWithResponseStream과, 하나의 장기 세션에서 여러 메시지를 주고받는 InvokeEndpointWithBidirectionalStream을 지원한다. 글은 직접 제어하는 컨테이너가 자체 요청 수용 한도를 적용하고 Amazon SageMaker AI가 기본 제공하는 동시성 신호를 활용할 수 있다는 점을 강조한다. 이 구조와 함께 AWS CDK 배포 단계에 측정 결과의 존재를 확인하는 조건을 두어, 추측한 자동 확장 설정이 조용히 운영에 반영되는 일을 막도록 설계했다.
4. 배포 사전 조건과 측정 산출물에 따른 리소스 생성
실습에는 IAM 역할, Amazon S3 버킷, Amazon ECR 저장소와 Amazon SageMaker AI 리소스를 생성할 권한, 대상 계정과 리전에 준비된 AWS CDK v2, Python 3.11 이상, uv 및 Docker가 필요하다. 확장 시간 측정을 위해 ml.g5.xlarge 할당량에는 기준 용량보다 최소 한 슬롯의 여유가 있어야 하며, 샘플의 PyTorch 고정 버전에는 torch 2.10.0에서 수정된 PYSEC-2026-2286이 있으므로 개념 검증을 넘는 사용 전에 검토와 업그레이드가 요구된다. 배포는 SpeechFoundationStack이 IAM과 모델 가중치 캐시용 S3 버킷을 만들고, SpeechModelCacheStack이 CodeBuild를 통해 Hugging Face 가중치를 캐시한 다음, SpeechEndpointStack이 이미지와 엔드포인트를 만드는 순서로 진행된다. max_instances가 min_instances보다 크면 scaling_enabled는 참이지만, 이것만으로 설정값이 실측되었다고 보장하지는 않는다. 세 번째 스택은 실행 가능한 plan 산출물까지 확인한 경우에만 EndpointAutoscaling과 EndpointObservability를 생성하므로, scaling_enabled가 참이어도 측정 산출물이 없으면 자동 확장 리소스는 만들어지지 않는다.
5. drift로 측정 전 배포 상태를 일치시키기
도구 체인의 첫 단계인 drift는 비용이 발생하거나 엔드포인트에 부하를 가하는 작업 전에 매번 실행하는 읽기 전용 대조 작업이다. 실제 배포된 확장 대상, 확장 정책, 경보 상태를 설정 파일이 기대하는 상태와 비교하며, 이전 모델에서 남은 정책이나 중단된 측정의 영향을 찾는다. 이런 불일치가 남아 있으면 측정 도중 용량이 바뀌어 단일 인스턴스의 처리 한계나 실제 확장 시간에 대한 결과를 오염시킬 수 있다. 정상 결과는 불일치가 없다는 사실과 사전 점검 통과 상태를 알리고, 이후 qmax 측정을 진행할 수 있게 한다. 글은 중단되거나 취소된 qmax 또는 ttotal 실행이 자동 확장을 한 인스턴스에 고정한 채 남는 경우를 흔한 원인으로 들며, 이때 thaw로 배포 정책을 복구해야 두 측정이 전제하는 설정과 실제 상태의 일치를 확보할 수 있다고 설명한다.
6. 고정 동시성 부하로 Q_max 측정하기
Q_max는 단일 인스턴스에서 대기 중인 요청과 실행 중인 요청을 합친 동시성을 기준으로, p95 첫 오디오 바이트 도달 시간이 SLO 안에 머무는 최대 수준이다. 측정은 동시성 N을 정확히 유지하는 폐쇄 루프 부하를 가하고 N을 단계적으로 높여 SLO 위반 지점을 찾는 방식으로 이루어진다. 글은 서버가 느려질 때 클라이언트의 요청도 줄어 실제 대기 지연을 놓치는 coordinated omission 문제를 피하기 위해 이 방식을 사용한다고 설명한다. qmax의 dry-run은 AWS 호출 없이 실행 일정과 예상 소요 시간을 출력하므로 약 36분인 실제 실행의 비용을 미리 가늠할 수 있다. 실제 실행은 자동 확장을 동결하고 용량을 한 인스턴스로 고정한 뒤 종료 시 자동 복구하므로, 여러 인스턴스의 효과가 섞이지 않은 인스턴스당 동시성 한계를 얻도록 한다.
7. Q_max = 50을 뒷받침하는 지연 측정 결과
부하 측정에서 동시 요청 수가 1, 5, 10, 20일 때 p95 첫 오디오 바이트 도달 시간은 각각 65.4ms, 286.2ms, 568.5ms, 1,129.3ms였고, 모두 3,000ms SLO를 충족했다. 동시 요청 30개와 40개에서도 각각 1,689.8ms와 2,245.0ms로 목표 안에 머물렀으며, 50개에서는 2,805.7ms를 기록했다. 다음 시험 단계인 60개에서는 3,374.8ms로 SLO를 위반했기 때문에 글은 Q_max를 50으로 정한다. 이는 단순히 50개까지 시험하고 멈춘 결과가 아니라 다음 단계에서 실제 위반을 확인한 결과라는 점에서, 시험한 단계 사이로 경계가 좁혀진 측정이다. 같은 실행에서 대기 없는 요청의 처리 시간은 평균 61.3ms와 p95 66.1ms로 측정되었으며, 글은 이 수치가 별도의 독립적인 경보에 쓰인다고 예고하지만 제공된 본문에는 그 경보의 상세 설명이 포함되어 있지 않다.
8. T_total의 단계별 측정과 제공된 본문의 한계
T_total은 추가 용량을 요청한 순간부터 그 용량이 정상 트래픽을 처리할 때까지 걸린 실제 시간이며, 도구는 배포 정책 자체의 감지 절차를 우회해 직접 확장을 강제한 뒤 구분 가능한 단계마다 시각을 기록한다. ttotal은 복구 여부를 판단할 때 qmax에서 측정한 부하 단계들을 사용하므로 해당 산출물을 입력으로 요구하고, 다른 스트리밍 전송 방식으로 측정한 산출물은 거부한다. 공개된 표에서 용량 요청부터 desired_set까지는 30.0초로 9.4%, desired_set부터 인스턴스가 로그에 나타나기까지는 180.8초로 56.5%였으며 후자가 가장 큰 구간이었다. 이어 컨테이너 시작까지는 3.7초로 1.2%, framework_init까지는 0.0초로 0.0%, weights_ready까지는 6.5초로 2.0%가 제시된다. 본문은 8개 측정 단계 중 이후 내용이 이어지기 전에 끊기므로, 전체 T_total과 나머지 단계 및 최종 확장·축소 임계값이나 쿨다운 수치는 제공된 자료만으로 확인할 수 없다.
🧾 핵심 주장 / 시사점
- 자동 확장 정책의 존재와 지연 SLO 충족은 별개다. 단일 인스턴스의 동시성 한계와 새 용량이 준비되는 시간을 함께 측정해야 추측한 설정이 숨기는 비용 및 지연 위험을 다룰 수 있다는 것이 글의 핵심이다.
- 측정 결과를 배포 조건으로 사용하는 방식은 측정을 단순한 사전 권고에서 실제 구성 생성의 필수 조건으로 바꾼다. 다만 plan 없이 자동 확장 리소스가 생성되지 않는다는 동작 자체가 충분한 처리 용량을 보장하는 것은 아니다.
- 공개된 확장 측정에서는 인스턴스가 로그에 나타나기까지의 구간이 56.5%로 지배적이었다. 이는 모델 가중치 준비 시간만으로 확장 지연을 설명할 수 없음을 보여주지만, 제공된 본문이 끊겨 전체 시간과 최종 정책의 적절성까지 평가할 수는 없다.
✅ 액션 아이템
- Q_max와 T_total 측정 전에 drift로 배포 상태와 설정의 일치 여부를 확인하고, 중단된 측정으로 용량이 고정된 경우 thaw로 복구.
- Q_max = 50과 T_total을 근거로 확장·축소 임계값 및 쿨다운을 산정하되, 현재 자료에 없는 T_total 전체 결과와 최종 수치 확인을 선행.
- 개념 검증을 넘어 사용하기 전에 샘플의 PyTorch 고정 버전을 검토하고 PYSEC-2026-2286에 대한 업그레이드 반영.
❓ 열린 질문
- Q_max = 50과 전체 T_total을 적용하면 확장·축소 임계값과 양쪽 쿨다운은 각각 얼마로 산정되는가?
- 제공된 본문에서 누락된 T_total의 나머지 단계와 전체 소요 시간은 얼마인가?
- ConcurrentRequestsPerModel과 클라이언트 측정값 사이의 비율 1.0은 다른 측정 조건에서도 유지되는가?